pax_global_header00006660000000000000000000000064144664075440014530gustar00rootroot0000000000000052 comment=5eb9bbd3f0f1c8553a8f7f4977c0e7be58181815 consolekit2-1.2.6/000077500000000000000000000000001446640754400137725ustar00rootroot00000000000000consolekit2-1.2.6/.gitignore000066400000000000000000000045011446640754400157620ustar00rootroot00000000000000Makefile Makefile.in aclocal.m4 config.cache autom4te.cache config.guess config.h config.h.in config.log config.status config.sub configure configure.scan compile depcomp intl libtool ltconfig ltmain.sh missing mkinstalldirs install-sh stamp-h stamp-h1 stamp-h.in version.h intl macros ABOUT-NLS INSTALL ChangeLog *.tar.gz *.tar.bz2 xml-i18n-extract.in xml-i18n-extract xml-i18n-merge.in xml-i18n-merge xml-i18n-update.in xml-i18n-update xmldocs.make omf.make gtk-doc.make *~ po/Makevars.template po/*.gmo po/*.header po/*.sed po/*.sin po/POTFILES po/Rules-quot po/stamp-po m4/* autotools/* cov-int/* data/consolekit.logrotate data/90-consolekit libconsolekit/libconsolekit-1.0.gir libconsolekit/libconsolekit-1.0.typelib libconsolekit/test-libconsolekit libconsolekit/libconsolekit.pc libconsolekit/.deps/ libconsolekit/.libs/ libconsolekit/libconsolekit.la libconsolekit/libconsolekit.lo libconsolekit/test-libconsolekit.o src/ck-manager-generated.c src/ck-manager-generated.h src/ck-seat-generated.c src/ck-seat-generated.h src/ck-session-generated.c src/ck-session-generated.h src/test-session src/test-seat src/test-session-leader src/test-manager src/ck-collect-session-info tools/pam-foreground-compat.ck tools/70-udev-acl.rules tools/71-udev-seat.rules tools/73-udev-seat-late.rules tools/ck-remove-directory doc/console-kit-daemon.1m doc/libconsolekit/Makefile.in doc/libconsolekit/html-build.stamp doc/libconsolekit/html.stamp doc/libconsolekit/setup-build.stamp doc/libconsolekit/libconsolekit-scan.c doc/libconsolekit/libconsolekit-decl.txt doc/libconsolekit/libconsolekit-decl-list.txt doc/libconsolekit/libconsolekit-decl-list.txt.bak doc/libconsolekit/libconsolekit-decl.txt.bak doc/libconsolekit/.libs/ doc/libconsolekit/gtkdoc-check.log doc/libconsolekit/gtkdoc-check.test doc/libconsolekit/gtkdoc-check.trs doc/libconsolekit/html/ doc/libconsolekit/libconsolekit-undeclared.txt doc/libconsolekit/libconsolekit-undocumented.txt doc/libconsolekit/libconsolekit-unused.txt doc/libconsolekit/libconsolekit.args doc/libconsolekit/libconsolekit.hierarchy doc/libconsolekit/libconsolekit.interfaces doc/libconsolekit/libconsolekit.prerequisites doc/libconsolekit/libconsolekit.signals doc/libconsolekit/scan-build.stamp doc/libconsolekit/sgml-build.stamp doc/libconsolekit/sgml.stamp doc/libconsolekit/test-suite.log doc/libconsolekit/xml/ ConsoleKit2.geany consolekit2-1.2.6/.tx/000077500000000000000000000000001446640754400145035ustar00rootroot00000000000000consolekit2-1.2.6/.tx/config000066400000000000000000000002361446640754400156740ustar00rootroot00000000000000[main] host = https://www.transifex.com [consolekit2.consolekit2pot] file_filter = po/.po source_file = po/ConsoleKit2.pot source_lang = en type = PO consolekit2-1.2.6/AUTHORS000066400000000000000000000004221446640754400150400ustar00rootroot00000000000000Current ConsoleKit2 Maintainers: -------------------------------- Antoine Jacoutot Robert Nagy Eric Koegel ConsoleKit Maintainer: ---------------------- William Jon McCann consolekit2-1.2.6/COPYING000066400000000000000000000431221446640754400150270ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. consolekit2-1.2.6/HACKING000066400000000000000000000043751446640754400147720ustar00rootroot00000000000000Making Changes ============== Please send all patches/pull requests to the ConsoleKit2 github repository: https://github.com/ConsoleKit2/ConsoleKit2 All patches should be against the latest version (see Source Code Repository). Patches can be added to the issue tracker. Source Code Repository ====================== - anonymous checkouts $ git clone git@github.com:ConsoleKit2/ConsoleKit2.git - checkouts over https $ git clone https://github.com/ConsoleKit2/ConsoleKit2.git - stage changed files $ git add -u - commit to local repository $ git commit - pull patch out of local repository to add to issue tracker $ git format-patch -1 - attach patch as an issue on the issue tracker - influential environment variables (set these in e.g. .bash_profile) export GIT_AUTHOR_NAME='Your Full Name' export GIT_COMMITTER_NAME='Your Full Name' export GIT_COMMITTER_EMAIL=youremail@domain.net export GIT_AUTHOR_EMAIL=youremail@domain.net - see also http://www.kernel.org/pub/software/scm/git/docs/ Committing Code =============== - Commit messages should be of the form (the five lines between the lines starting with ===) === begin example commit === short explanation of the commit Longer explanation explaining exactly what's changed, whether any external or private interfaces changed, what bugs were fixed (with bug tracker reference if applicable) and so forth. Be concise but not too brief. === end example commit === - Always add a brief description of the commit to the _first_ line of the commit and terminate by two newlines (it will work without the second newline, but that is not nice for the interfaces). - First line (the brief description) must only be one sentence. It should optionally reference issue tracker numbers if they exist. - The main description (the body) is normal prose and should use normal punctuation and capital letters where appropriate. Normally, for patches sent to a mailing list it's copied from there. - When committing code on behalf of others use the --author option, e.g. git commit -a --author "Joe Coder " Coding Style ============ - Follow the coding style already used - Write docs for all functions and structs and so on. We use gtkdoc format. consolekit2-1.2.6/Makefile.am000066400000000000000000000030431446640754400160260ustar00rootroot00000000000000# This file will be processed with automake-1.7 to create Makefile.in AUTOMAKE_OPTIONS = 1.7 NULL = ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} SUBDIRS = \ src \ libconsolekit \ libck-connector \ tools \ data \ doc \ pam-ck-connector \ po \ $(NULL) EXTRA_DIST = config.rpath \ COPYING \ AUTHORS \ INSTALL \ README \ HACKING \ NEWS \ ChangeLog \ m4 \ gtk-doc.make \ $(NULL) DISTCLEANFILES = \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ intltool-*.in \ compile \ configure \ INSTALL \ install-sh \ missing \ mkinstalldirs \ config.guess \ ltmain.sh \ config.sub \ depcomp \ Makefile.in \ config.h.* \ aclocal.m4 \ $(NULL) # Creating ChangeLog from git log (taken from cairo/Makefile.am): ChangeLog: $(srcdir)/ChangeLog $(srcdir)/ChangeLog: @if test -d "$(srcdir)/.git"; then \ (cd "$(srcdir)" && \ ./missing --run git log --stat) | fmt --split-only > $@.tmp \ && mv -f $@.tmp $@ \ || ($(RM) $@.tmp; \ echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ (test -f $@ || echo git-log is required to generate this file >> $@)); \ else \ test -f $@ || \ (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ echo A git checkout and git-log is required to generate this file >> $@); \ fi .PHONY: ChangeLog $(srcdir)/ChangeLog DISTCHECK_CONFIGURE_FLAGS = \ --enable-introspection \ --enable-gtk-doc \ --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) consolekit2-1.2.6/NEWS000066400000000000000000000652521446640754400145030ustar00rootroot00000000000000============== Version 1.2.6 ============== Stable release of ConsoleKit2 Changes since 1.2.4 New Features: - Use 0 as a starting point for the seat serial and lowercase the seat name as well to imitate systemd/logind - Enable VT support for __aarch64__ Bug Fixes: - Do not call g_close() on invalid file descriptors - Properly handle PROP_KIND in ck_seat_get_property() Misc Changes: - Simplify ck_system_can_suspend on OpenBSD ============== Version 1.2.5 ============== Stable release of ConsoleKit2 Changes since 1.2.4 New Features: - Use sd_* shim functions on !systemd platforms Bug Fixes: - Fix gtk-doc test failure Misc Changes: - Sleep before suspending or hibernating to give time for the screen to lock - Remove pm-utils dependency ============== Version 1.2.4 ============== Stable release of ConsoleKit2 Changes since 1.2.3 New Features: - Implement session-service parameter Bug Fixes: - Do not hardcode seat0 for Seat1 in ListSessions ============== Version 1.2.3 ============== Stable release of ConsoleKit2 Changes since 1.2.2 Bug Fixes: - Fix a crash with glib debugging enable by not unreferencing an instance object which was not referenced before while removing the lock on it. Translation Updates: French ============== Version 1.2.2 ============== Stable release of ConsoleKit2 Changes since 1.2.1 Bug Fixes: - Use the named pipe's random filepath as a lock reference - Fix signal handling with multiple inhibit events Misc Changes: - Merge enhancements from the OpenBSD port - Remove unused argument from the get_named_pipe_path() function ============== Version 1.2.1 ============== Stable release of ConsoleKit2 Changes since 1.2.0 New Features: - Add ListSeats method to Manager interface - Add CanControlSession dbus call Bug Fixes: - Correctly report SELinux support - Only use tmpfs mounts on DFly if supported - incompatible-pointer-type warning - Remove some redundant code probing for hibernation, suspend, and sleep - make_tmpfs for DragonFly - memory leak in ck-manager - Seat property on Session interface Misc Changes: - Add DragonFlyBSD as a platform - Remove DragonFly specific code from FreeBSD sysdeps - Switch away from AC_DISABLE_STATIC ============== Version 1.2.0 ============== Stable release of ConsoleKit2 Changes since 1.1.2 New Features: - Add wscons headers for OpenBSD Bug Fixes: - Allow changing to VTs we don't have a session for - Correct introspection prefixes - Change configure.ac to enable the udev backend with devattr - Use KDSKBMODE if defined - Use #ifdef HEADER_H instead of #ifdef OS - FreeBSD session activation - Place sessions with a VT on the static Seat1 - clean up clang warnings - correct uninitialized variable warning - Explicitly check for needed symbols - Correct build errors in OpenBSD - fix compiling on FreeBSD Misc Changes: - update gitignore - more autotools cleanup work - update readme with new deps ============== Version 1.1.2 ============== [Please note that this is a development release.] New Features: - add a session-state property and method - Add session-class dbus property and get method - introduce libconsolekit - Add dbus method GetVTNr to Session - add dbus LockSession/UnlockSession - add dbus ActivateSession/ActivateSessionOnSeat Bug Fixes: - add session class + state to ck-list-sessions - Allow session-class property to be set via OpenSessionWithParameters - wrong lib linked in libconsolekit.pc.in - remove the rest of the gcc warnings - remove warnings about signed/unsigned comparisons - remove warning about redeclaration - remove warnings about redundant function declarations - fix --enable-libudev configure flag - coverity: 180820 remove dead code Misc Changes: - add CONSOLEKIT_DEBUGGING support back in - update ck-list-sessions man page - update tests for new methods added - simplify configure.ac - document session types allowed - ============== Version 1.1.1 ============== [Please note that this is a development release.] Changes: - Don't try to run "chmod +x" on 90-consolekit, it is not a executable. - Use INSTALL_SCRIPT instead of INSTALL_PROGRAM for 90-consolekit. - Remove the root restriction for XDG_RUNTIME_DIR. - cgroups: Attempt to use 'cpuaccount' if 'all' cgroup fails on pid move - ck-remove-directory: return exit code 0 on success - ck-remove-directory: remove unused dest parameter on become_user - ck-remove-directory: remove dest dir as real user - Add support for selinux - Freebsd 10.3: Fix session activation - Fix a reversed condition for invalid device on NetBSD - cgroups: Use UID of logged in user instead UID of session leader process - Fix memory leaks and a memory corruption issue. - OpenBSD: adapt to recent kvm(3) restrictions - Fix pam-ck-connector on musl - Fix for OpenBSD and FreeBSD VT device naming scheme. - Add a few more display manager users to filter out. - Update udev rules. - Handle XDG_RUNTIME_DIR not being created/set. - Add support for server managed FDs. - Prevent a use-after-free when emitting signal changes. - Fix coverity and gcc warnings. - Add a LockedHint property. ============== Version 1.1.0 ============== [Please note that this is a development release.] Development release of ConsoleKit2 targeting the 1.2 release. Please report all problems to https://github.com/ConsoleKit2/ConsoleKit2/issues Changes: - Add a 'User' section to the CK database - Add a 'Seats' section to the CK database - Properly filter the sessions for the specified user - pam-ck allow VTNR to be double-digit - login_session_id will be G_MAXUINT32 when unset - Handle the legacy 'user' property as an override setting - Change owner of newly created cgroup to owner of progress group leader - Create cgroup on all controllers managed by cgmanager - Implement XDG_RUNTIME_DIR - When assigning session to active VT prefer graphical sessions - Fix undefined behavior in ck-log-system-start Translation Updates: Bulgarian, Spanish, Spanish (Latin America), Dutch, Russian ============== Version 1.0.1 ============== Stable release of ConsoleKit2. Thank you to everyone who submitted pull requests. Changes since 1.0.0: - Check for enough swap space before allowing hibernate operation - XDG_VTNR support - Add NetBSD support - Fix a potential crash condition after successfully suspending. - Fix some libdir/scripts stuff - Filter out the kdm user ============== Version 1.0.0 ============== Stable release of ConsoleKit2 This is the first release of ConsoleKit2 considered stable. It incorporates many changes since the fork from ConsoleKit. Please see the previous development release notes for the full list of changes. Notable changes since 0.9.5: - On Linux, if cgmanager is installed and running, ConsoleKit2 will use it to track the sessions. The method of session tracking supersedes the XDG_SESSION_COOKIE - Respect multilib/multiarch filesystem layouts. Patch by Kylie McClain - Filter out the sddm user the same as the gdm user - Update the gettext portion of the build system - Prevent an infinite loop when removing inhibitors - Add Bulgarian language translations ============== Version 0.9.5 ============== [Please note that this is a development release.] Development release of ConsoleKit2 targeting the 1.0 release. Please report all problems to https://github.com/ConsoleKit2/ConsoleKit2/issues - Add new DBUS method: ListInhibitors - Mark sessions as local explicitly when not built with PAM support - Watch and handle dbus NameOwnerChanged events - Add an --enable-tests configure option ============== Version 0.9.4 ============== [Please note that this is a development release.] Development release of ConsoleKit2 targeting the 1.0 release. Please report all problems to https://github.com/ConsoleKit2/ConsoleKit2/issues - Cksession return empty string when login session id not set - Test code now cleans up any created sessions - Fix issue #26, where polkit and networkmanager weren't working because the CKDB wasn't getting the correct uid set. Translation Updates: Russian, Spanish, Spanish (Latin America) ============== Version 0.9.3 ============== [Please note that this is a development release.] Development release of ConsoleKit2 targeting the 1.0 release. Please report all problems to https://github.com/ConsoleKit2/ConsoleKit2/issues Changes to the public DBUS API: - Adds the "mode" parameter to the inhibit call - Additional error messages are now returned i.e. CkSeat's ActivateSession can return CK_SEAT_ERROR_ALREADY_ACTIVE - PrepareForSleep PrepareForShutdown signals added - Coverity scan and cppcheck static analysis fixes - Don't delete the inhibit named pipe files on startup - Add "mode" to the inhibit dbus call to better match logind - Remove the pam-foreground-compat script, it was causing race conditions - Port ConsoleKit2 to GDBus, these changes required a glib min version bump to 2.40 - A TRACE macro was added for additional debugging when built with --enable-debug=full - Add transifex client configuration - Fix build without PolicyKit/Polkit (Ivailo Monev) - Include gio header required for GAsyncResult (Ivailo Monev) - OpenBSD: unbreak get_kinfo_proc by properly initializing the length (Antoine Jacoutot) - Check for Linux-PAM features rather than just Linux, for OpenPAM support. (Andrew Aldridge) - Fix a warning message about the Source ID not being found during remote ck session log out. - Add -with-rundir configure flag (Robby Workman) - Revert the "Fix crash on logout/login via SunRay" as it caused regressions - OpenBSD cleanups and sync (Antoine Jacoutot) - PrepareForSleep/Shutdown signals are now emitted - Ensure the 90-consolekit file is correctly installed - SystemdService file is now conditionally installed - Fix installing the logrotate file Translation Updates: Russian, Spanish, Spanish (Latin America) ============== Version 0.9.2 ============== [Please note that this is a development release.] Development release of ConsoleKit2 targeting the 1.0 release. Please report all problems to https://github.com/ConsoleKit2/ConsoleKit2/issues Changes to the public DBUS API: - Adds the PowerOff/Reboot and respective Can APIs. - Adds the PolkicyKit interactivity flag to the API calls. Same as logind. Other minor changes: - Default to not building systemd units - Add a note about CONFIG_AUDITSYSCALL and PAM - Minor autotools changes. - Change inhibit locks internally to allow multiple instances of the same application to hold a lock. ============== Version 0.9.1 ============== [Please note that this is a development release.] Development release of ConsoleKit2 targeting the 1.0 release. Please report all problems to https://github.com/ConsoleKit2/ConsoleKit2/issues Only one commit with this release but since it changes the public DBUS API it's better to get it out now before someone starts writing for the 0.9.0 APIs. Hybrid Suspend has been added as a sleep method. The sleep API has been reworked to emulate logind so that supporting both is easier. ============== Version 0.9.0 ============== [Please note that this is a development release.] Development release of ConsoleKit2 targeting the 1.0 release. Please report all problems to https://github.com/ConsoleKit2/ConsoleKit2/issues ConsoleKit2 is a fork of ConsoleKit since it is no longer maintained. Added OpenBSD and DragonFlyBSD backends, pulled in FreeBSD and GNU/kFreeBSD provided to the ConsoleKit bugtracker or on distro's public repositories. As well as many other patches floating around so that distributions no longer have to carry large patchsets. Please report any other patches required or currently in use and those can be added as well. The 63 threads issue has been resolved if the Linux kernel has support for the notification required. ConsoleKit2 supports suspending and hibernation for Linux, FreeBSD, DragonFlyBSD, and OpenBSD through a DBUS API. * Add in the logrotate and consolekit xinitrc script and install them to their standard location with configure switches. * Add a new DBUS interfaces for suspend/hibernation of the system as well as the ability to inhibit it and stop/reeboot actions. * Translation support added. * Check the return value of sysconf before passing it to calloc. * Only close fds that were opened. * Fix a resource leak. * ck-log-system-start: always create log directory. Patch by Daniel Drake. * Prevent possible use-after-free condition. Patch by Anders Kaseorg. * Fix crash on logout/login via SunRay. Patch by Halton Huo. * Fix ck-history truncating login names. * Call thread_data_free before g_thread_exit. * Add man pages. Patch by Brian Cameron. * Fix for rejected GetAll properties by GDBus. Patch by Teodor MICU. * Linux: Use /sys/class/tty/tty0/active for VT change notifications (the 63 threads issue) * Set source id to 0 after calling g_source_remove. Patch by Manfred Hampl. * Return early when remote DISPLAY variable set. Patch by Joe Mullally. * Various deprecated functions and other compile warnings were fixed. * Add an --enable-debug=full which always enables debugging. * Add OpenBSD backend. Patches by Robert Nagy and ajacoutot. * Improve FreeBSD backend. * Add DragonFlyBSD backend. * Be able to shutdown or reboot even without polkit or RBAC support. Patch by Romain Perier. * udev-acl install to usr. * Add support for devices with long names. Patch by Aleix Conchillo Flaqué. * Cleanup console tag files on application startup and shutdown. * Fix uninitialized variable. * Use correct type in tools/ck-history.c Patch by Rafal Muzylo. * Add a configure switch for PolicyKit. Patch by Samuli Suominen. * Enables the FreeBSD VT ioctls on GNU/kFreeBSD. Patch by Robert Millan. * Fallback to getpeereid() on FreeBSD and GNU/kFreeBSD. Patch by Robert Millan. ============== Version 0.4.6 ============== NOTE: ConsoleKit is no longer actively maintained and this will most likely be the final release. You are advised to switch to logind: http://www.freedesktop.org/software/systemd/man/systemd-logind.service.html * Don't truncate --frequent output to 8 chars in ck-history (Ray Strode) * Import udev-acl tool from udev (Michael Biebl) * Add support for GNU/Hurd (Pino Toscano) * Build system fixes (Samuli Suominen) ============== Version 0.4.5 ============== * Loop around opening /dev/console to deal with BKL-less kernels (Colin Watson) * systemd fixes (Lennart Poettering) ============== Version 0.4.4 ============== * systemd fixes (Lennart Poettering) ============== Version 0.4.3 ============== * Revert VT_WAITEVENT usage, since it is racy (Lennart Poettering) * systemd fixes (Lennart Poettering) ============== Version 0.4.2 ============== * Ensure we only care for seat files ending in .seat (William Jon McCann) * Various Solaris improvements (Halton Huo) * Make build silent (Ray Strode) * Don't take bus name until ready (Ray Strode) * systemd hookup (Lennart Poettering) * add --since option to ck-history (William Jon McCann) * Reduce number of threads on Linux (Kan-Ru Chen) * Other fixes (Anders Kaseor, Frederic Crozat, Matthias Clasen, Michael Biebl, William Jon McCann) ============== Version 0.4.1 ============== * Fix a crasher (William Jon McCann) * fix a small memory leak (Matthias Clasen) * update email address (William Jon McCann) ============== Version 0.4.0 ============== * Starting with this release we will not do session.d/ 'session_active_changed' callouts anymore. (Lennart Poettering) * get rid of session.d's session_active_changed callout (Lennart Poettering) * close file descriptors before exit func (Halton Huo) * log the kernel release and boot arguments at start time (William Jon McCann) * show display in host field if the host isn't set (William Jon McCann) * print the uptime for the reboot items in the report (William Jon McCann) * fix logic for finding session remove events (William Jon McCann) * fix a few small leaks (William Jon McCann) * Add seat.d/ callout directory and guarantee we dump the database before call * database: write the console database to disk before signalling via dbus (Len * Enforce that the env array has the right size (Lennart Poettering) * when printing size_t use %z format string (Lennart Poettering) * make CK database world readable (Lennart Poettering) * get rid of ck_seat_set_active_session() prototype since no such function exi * Move ck_session_run_programs() from ck-run-programs.h to ck-session.h (Lenna * post release version bump (Ray Strode) ============== Version 0.3.1 ============== * port to PolicyKit 1.0 (Matthias Clasen) * D-Bus policy updates (Colin Walters, Martin Pitt, Vincent Untz, William Jon McCann) * better diagnostic information for unimplemented backends (Daniel Macks) * file monitoring fixes (James Westby) * get VT from X display if no controlling tty is available (Ray Strode) * add "nox11" option to PAM module (Martin Pitt) * parse log entries with no body correctly (William Jon McCann) * fix zero-sized struct/unions (William Jon McCann) * solaris build fixes (Halton Huo) * parse gecos field for real name (William Jon McCann) * leak fixes (James Westby, Steve Langasek) * compile warning fixes (Matthias Clasen) * fix doc xml validation errors (William Jon McCann) * fix doc generation when srcdir != builddir (Ray Strode) * add example upstart events for logging (William Jon McCann, Ray Strode) * fix ChangeLog generation script to work with git-log moved to libexecdir (Ray Strode) ============== Version 0.3.0 ============== * API changes to make the daemon conform to the published spec * don't allow reboot if PolicyKit and RBAC are disabled (William Jon McCann) * fix path in includes (William Jon McCann) * reorganize the docs a bit (William Jon McCann) * pull updated DTD and xsl from DeviceKit-disks (William Jon McCann) * fix distcheck (William Jon McCann) * still having problems using xinclude (William Jon McCann) * fix the includes (William Jon McCann) * add missing bits (William Jon McCann) * use spec files directly as introspection xml and try to generate docs on the fly (William Jon McCann) * use object paths for seat added/removed signals per spec (William Jon McCann) * regenerate the docs and xml from the spec (William Jon McCann) * add GetLoginSessionId to exported interface (William Jon McCann) * fix use of unix-user as int (William Jon McCann) * use fortify source flag when building from git (William Jon McCann) * fix location of scripts again (William Jon McCann) * dist bzip by default (William Jon McCann) * fix up signal definition (William Jon McCann) * fix UnixUser to be uint (William Jon McCann) * use object paths instead of strings for signals (William Jon McCann) * cleanly shutdown event logging thread (William Jon McCann) * export login session id to the bus (William Jon McCann) * exit with the bus now that we're activated by the bus (William Jon McCann) * allow retaining authorizations for {stop,restart}-multiple-users (David Zeuthen) * make sure to add all override parameters (William Jon McCann) * fix the script to work with recent dbus-python api changes (William Jon McCann) * always try to detect parameters for session (William Jon McCann) * oops one more place (William Jon McCann) * install scripts into $(prefix)/lib instead of $libdir (William Jon McCann) * return PolicyKit results when not privileged for action (William Jon McCann) * fix typo (William Jon McCann) * initial login session id support (William Jon McCann) * display uid as unix-user to match api (William Jon McCann) * fix packaging of policy file (William Jon McCann) * rename policy file (William Jon McCann) * post release version bump (William Jon McCann) ============== Version 0.2.10 ============== * always create the directories we need (William Jon McCann) * properly get display device on Solaris (Simon Zheng) * fix solaris x11-display-device when no vt available (Brian Cameron) * solaris doesn't like printing null (Brian Cameron) * fix display of active vt when vt is disabled (Brian Cameron) * fix solaris vt handling to work when no vt available (Brian Cameron) * improve supporting Solaris VT switching (Simon Zheng) * don't include paths.h on systems that don't have it (William Jon McCann) * create the log file with S_IROTH and don't touch the log on build (William Jo ============= Version 0.2.9 ============= * ck_seat_get_active_session shouldn't return a null ssid (William Jon McCann) * guard against writing null string to keyfile (William Jon McCann) * reverse the sense of the dbus policy (William Jon McCann) * add a ck-launch-session tool (William Jon McCann) * don't set the session-type to the command name (William Jon McCann) ============= Version 0.2.8 ============= * add tools to log restart and stop events (William Jon McCann) * fix typo in dbus policy file (William Jon McCann) * touch the history file to create it for people not using packages (William Jon McCann) * mkdir /var/log/ConsoleKit at install time (William Jon McCann) * set a global flag so that D-Bus does not change the SIGPIPE handler in the PAM module (William Jon McCann) * when a parsing error occurs don't return an empty event (William Jon McCann) ============= Version 0.2.7 ============= * update gitignore files (William Jon McCann) * add a helper to write a system start record to the CK history (William Jon McCann) * add support for logging start/stop/restart (William Jon McCann) * fix typo in man page (William Jon McCann) * make autogen work with aclocal 1.10 (Marc-Andre Lureau) * allow session type filtering for all report formats (William Jon McCann) * make polkit optional and use RBAC on Solaris (Brian Cameron) * fixes for solaris (Brian Cameron) * add session-type filtering to ck-history (William Jon McCann) * try to activate x11-display-device not only display-device (William Jon McCann) ============= Version 0.2.6 ============= * be a little smarter about how we compute the number of users (William Jon McCann) * fix policy action name (William Jon McCann) ============= Version 0.2.5 ============= * use /var/log/ instead of /var/run for log file ============= Version 0.2.4 ============= * actually register the error type with dbus (William Jon McCann) * add GetSessions method to Manager interface (William Jon McCann) * add error type to manager (William Jon McCann) * initial stop/restart support (William Jon McCann) * use VT_GETSTATE and tty0 to identify a console_ioctl on linux (Peter Jones) * remove obsolete sysv init script (Michael Biebl) * start CK service on-demand using D-Bus system activation (Michael Biebl) * dump session leader info (William Jon McCann) * error out if unknown options are passed on command line (William Jon McCann) * move session leader stuff into a separate class (William Jon McCann) * try to handle log rotation (William Jon McCann) * add support for reporting from logrotated files (William Jon McCann) * add a basic --frequent report (William Jon McCann) * Merge branch 'master' of git+ssh://git.freedesktop.org/git/ConsoleKit (William Jon McCann) * add last mode, filtering by user/seat; shorten logged ids (William Jon McCann) * add bugzilla url (William Jon McCann) * check for oldest being null (William Jon McCann) * rename --last to --last-compat (William Jon McCann) * a few fixes for last patch (William Jon McCann) * add a last compatible outout format to ck-history (William Jon McCann) * use AC_GNU_SOURCE instead of #define (William Jon McCann) * add a basic ck-history command (William Jon McCann) * add event logging capability (William Jon McCann) * remove emacs modeline (William Jon McCann) * maintain a file with the dump of the local database (David Zeuthen) * remove session/seat from list before signaling (William Jon McCann) * add a way to synchronously run programs on session add/remove/activity_change (David Zeuthen) * don't use VT_GETSTATE when VT is unavailable (Brian Cameron) * try to make things work for systems that don't support VT_ACTIVATE etc (William Jon McCann) * add wiki to readme (William Jon McCann) * post release version bump (William Jon McCann) ============= Version 0.2.3 ============= * Use unix-user instead of user so that PAM module works ============= Version 0.2.2 ============= Major changes in this release: * FreeBSD support (Joe Marcus Clarke & Florent Thoumie) * Solaris support (Brian Cameron & William Jon McCann) * More abstraction of system dependent stuff (William Jon McCann) * Experimental support for seat & device configuration (William Jon McCann) * Add new helper for getting tty from DISPLAY (William Jon McCann) * a few fixes for getfd suggested by Lennart (William Jon McCann) ============= Version 0.2.1 ============= * disable static libs * use inotify to detect activity on tty when possible * add support for CKCON_X11_DISPLAY_DEVICE environment variable * daemonize earlier * daemonize quietly (David Zeuthen) * add syslog support * properly detect unix-user for OpenSession * use xlib directly for tools * add CanActivateSessions to Seat interface * install fixes (Doug Goldstein) ============= Version 0.2.0 ============= * add PAM module and connector library (David) * restrict the use of D-Bus property get/set by default * add x11-display-device property * add unix-user property and deprecate user property * rename host-name property to remote-host-name * make OpenSession asynchronously collect information for session * add basic idle monitoring of text sessions * add backend tools / framework * add uuid to cookie * rename list session tool * add docbook documentation * add spec framework * fix some leaks ============= Version 0.1.2 ============= * don't use NULL parameters * add system-idle-hint and system-idle-since-hint * add session idle-hint and idle-since-hint * add session creation time * don't spew errors when can't get a console fd * improve thread safety in vt monitor * split output of list-sessions onto separate lines * create/delete pid file (caglar) ============= Version 0.1.1 ============= * use the supplied vt number when updating active session * add support for reconnecting the the system bus * start before HAL (David) * don't keep last session active when switching without one (David) * make threads use small stack size rather than the default (Matthias) * change a console-kit to ConsoleKit in a few places * add more debugging output ============= Version 0.1.0 ============= ConsoleKit * First public release consolekit2-1.2.6/README000066400000000000000000000043341446640754400146560ustar00rootroot00000000000000What is ConsoleKit2? =================== ConsoleKit2 is a framework for defining and tracking users, login sessions, and seats. It allows multiple users to be logged in at the same time and share hardware for their graphical session. ConsoleKit2 will keep track of those resources and whichever session is active will have use of the hardware at that time. What is a seat? =============== A seat is a collection of sessions and a set of hardware (usually at least a keyboard and mouse). Only one session may be active on a seat at a time. What is a session? ================== A session is a collection of all processes that originate from a single common ancestor and retain knowledge of a secret. As an implementation detail, this secret may be stored in the process environment by the login manager under the name XDG_SESSION_COOKIE. Minimum Requirements ==================== * Autotools (for building ConsoleKit2) * Gettext 0.15 * glib 2.40 * X11 * zlib * libkvm (required for OpenBSD, FreeBSD, kfreebsd, and DragonFlyBSD) * xsltproc * gtk-doc (optional) * GObject Introspection (optional) * PolicyKit/Polkit 0.92 (optional) * PAM (optional) * libudev or libdevattr (optional, for session-controller support) * libdrm (optional, for session-controller support) * proplib (optional, for session-controller support on DragonFlyBSD) * xmlto (optional, for documentation) * inotify (optional) * RBAC (optional) * pm-utils (optional, but required for suspend/hibernate on Linux) * cgmanager + libnih (recommended on Linux, for process tracking) * selinux (optional) Additionally, on Linux CONFIG_AUDITSYSCALL=y is required for pam_ck_connector.so to work (PAM support). More Information ================ Documentation is available at: https://consolekit2.github.io/ConsoleKit2 Report bugs and feature requests to: https://github.com/ConsoleKit2/ConsoleKit2/issues Translation is handled with Transifex, please register at: https://www.transifex.com/projects/p/consolekit2/ The main development follows the standard github work flow and happens at: https://github.com/ConsoleKit2/ConsoleKit2 ConsoleKit2 is a fork of ConsoleKit since it is no longer maintained. Information on ConsoleKit can be found at: http://freedesktop.org/wiki/Software/ConsoleKit/ consolekit2-1.2.6/TODO000066400000000000000000000007511446640754400144650ustar00rootroot00000000000000TODO ==== - Patch all login managers to open CK sessions - Make a registration interface for per-session idle time delegates - Report idle time per Seat - Establish what session-types should be - Improve the ck-list-sessions interface - Complete the documentation - Make openssh report sessions correctly Not as easy as just using the PAM module. - Figure out how to register activation handlers - Use a configuration file for defining how to add sessions to seats consolekit2-1.2.6/acinclude.m4000066400000000000000000000045041446640754400161660ustar00rootroot00000000000000 dnl EXTRA_COMPILE_WARNINGS dnl Turn on many useful compiler warnings dnl For now, only works on GCC AC_DEFUN([EXTRA_COMPILE_WARNINGS],[ dnl ****************************** dnl More compiler warnings dnl ****************************** AC_ARG_ENABLE(compile-warnings, AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@], [Turn on compiler warnings]),, [enable_compile_warnings="m4_default([$1],[yes])"]) warnCFLAGS= if test "x$GCC" != xyes; then enable_compile_warnings=no fi warning_flags= realsave_CFLAGS="$CFLAGS" case "$enable_compile_warnings" in no) warning_flags= ;; minimum) warning_flags="-Wall" ;; yes) warning_flags="-Wall -Wmissing-prototypes" ;; maximum|error) warning_flags="-Wall -Wmissing-prototypes -Wnested-externs -Wpointer-arith" CFLAGS="$warning_flags $CFLAGS" for option in -Wno-sign-compare; do SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $option" AC_MSG_CHECKING([whether gcc understands $option]) AC_TRY_COMPILE([], [], has_option=yes, has_option=no,) CFLAGS="$SAVE_CFLAGS" AC_MSG_RESULT($has_option) if test $has_option = yes; then warning_flags="$warning_flags $option" fi unset has_option unset SAVE_CFLAGS done unset option if test "$enable_compile_warnings" = "error" ; then warning_flags="$warning_flags -Werror" fi ;; *) AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings) ;; esac CFLAGS="$realsave_CFLAGS" AC_MSG_CHECKING(what warning flags to pass to the C compiler) AC_MSG_RESULT($warning_flags) AC_ARG_ENABLE(iso-c, AC_HELP_STRING([--enable-iso-c], [Try to warn if code is not ISO C ]),, [enable_iso_c=no]) AC_MSG_CHECKING(what language compliance flags to pass to the C compiler) complCFLAGS= if test "x$enable_iso_c" != "xno"; then if test "x$GCC" = "xyes"; then case " $CFLAGS " in *[\ \ ]-ansi[\ \ ]*) ;; *) complCFLAGS="$complCFLAGS -ansi" ;; esac case " $CFLAGS " in *[\ \ ]-pedantic[\ \ ]*) ;; *) complCFLAGS="$complCFLAGS -pedantic" ;; esac fi fi AC_MSG_RESULT($complCFLAGS) WARN_CFLAGS="$warning_flags $complCFLAGS" AC_SUBST(WARN_CFLAGS) ]) consolekit2-1.2.6/autogen.sh000077500000000000000000000022301446640754400157700ustar00rootroot00000000000000#!/bin/sh # Run this to generate all the initial makefiles, etc. srcdir=`dirname $0` test -z "$srcdir" && srcdir=. (test -f $srcdir/configure.ac) || { echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" echo " top-level package directory" exit 1 } GTKDOCIZE=$(which gtkdocize 2>/dev/null) if test -z $GTKDOCIZE; then echo "You don't have gtk-doc installed, and thus won't be able to generate the documentation." rm -f gtk-doc.make cat > gtk-doc.make <, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | pw32* | os2*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux*) case $cc_basename in icc* | ecc*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; sco3.2v5*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) wl='-Wl,' ;; sysv4*MP*) ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix3*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | kfreebsd*-gnu) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. libname_spec='lib$name' case "$host_os" in aix3*) ;; aix4* | aix5*) ;; amigaos*) ;; beos*) ;; bsdi[45]*) ;; cygwin* | mingw* | pw32*) shrext=.dll ;; darwin* | rhapsody*) shrext=.dylib ;; dgux*) ;; freebsd1*) ;; kfreebsd*-gnu) ;; freebsd* | dragonfly*) ;; gnu*) ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac ;; interix3*) ;; irix5* | irix6* | nonstopux*) case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux*) ;; knetbsd*-gnu) ;; netbsd*) ;; newsos6) ;; nto-qnx*) ;; openbsd*) ;; os2*) libname_spec='$name' shrext=.dll ;; osf3* | osf4* | osf5*) ;; solaris*) ;; sunos4*) ;; sysv4 | sysv4.3*) ;; sysv4*MP*) ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) ;; uts4*) ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <@]) AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal) # Solaris requires libresolv for daemon() case "$host_os" in solaris*) AC_CHECK_LIB(resolv, daemon, [CK2_LIBS="$CK2_LIBS -lresolv"]) ;; kfreebsd*-gnu) have_getpeereid=no AC_CHECK_LIB(bsd, getpeereid, have_getpeereid=yes) if test "x$have_getpeereid" = "xyes"; then CK2_LIBS="${CK2_LIBS} -lbsd" TOOLS_LIBS="${TOOLS_LIBS} -lbsd" AC_DEFINE(HAVE_GETPEEREID, [], [Define if we have getpeereid]) fi ;; esac dnl --------------------------------------------------------------------------- dnl - Are we specifying a different dbus root ? dnl --------------------------------------------------------------------------- AC_ARG_WITH(dbus-sys, [AS_HELP_STRING([--with-dbus-sys=],[where D-BUS system.d directory is])]) AC_ARG_WITH(dbus-services, [AS_HELP_STRING([--with-dbus-services=],[where D-BUS services directory is])]) if ! test -z "$with_dbus_sys" ; then DBUS_SYS_DIR="$with_dbus_sys" else DBUS_SYS_DIR="$sysconfdir/dbus-1/system.d" fi AC_SUBST(DBUS_SYS_DIR) dnl --------------------------------------------------------------------------- dnl - Check for libz dnl --------------------------------------------------------------------------- have_libz=no AC_CHECK_LIB(z, compress, [AC_CHECK_HEADER(zlib.h, [have_libz=yes], [])], []) if test "x$have_libz" != "xyes"; then AC_MSG_ERROR([Unable to find libz]) fi Z_LIBS="${Z_LIBS} -lz" AC_SUBST(Z_LIBS) dnl --------------------------------------------------------------------------- dnl - Path to rundir e.g. /var/run dnl --------------------------------------------------------------------------- AC_ARG_WITH(rundir, [AS_HELP_STRING([--with-rundir=],[run directory location, e.g. /var/run])]) if ! test -z "$with_rundir" ; then RUNDIR="$with_rundir" else RUNDIR="$localstatedir/run" fi AC_SUBST(RUNDIR) dnl --------------------------------------------------------------------------- dnl - PID file dnl --------------------------------------------------------------------------- AC_ARG_WITH(pid-file, [AS_HELP_STRING([--with-pid-file=],[pid file location])]) if ! test -z "$with_pid_file"; then CONSOLE_KIT_PID_FILE=$with_pid_file else CONSOLE_KIT_PID_FILE=${RUNDIR}/ConsoleKit/pid fi AC_SUBST(CONSOLE_KIT_PID_FILE) dnl --------------------------------------------------------------------------- dnl Figure out what tools backend to build dnl --------------------------------------------------------------------------- CK_BACKEND="" KVM_LIBS="" case "$host" in *-*-openbsd*) CK_BACKEND="openbsd" AC_CHECK_LIB(kvm, kvm_openfiles, have_kvm=yes, AC_MSG_ERROR([Unable to find libkvm which is needed on OpenBSD])) if test "x$have_kvm" = "xyes"; then KVM_LIBS="-lkvm" fi ;; *-*-freebsd* | *-*-kfreebsd*-gnu ) CK_BACKEND="freebsd" AC_CHECK_LIB(kvm, kvm_openfiles, have_kvm=yes, AC_MSG_ERROR([Unable to find libkvm which is needed on FreeBSD/DragonflyBSD])) if test "x$have_kvm" = "xyes"; then KVM_LIBS="-lkvm" fi AC_CHECK_LIB(procstat, procstat_open_sysctl, have_procstat=yes, AC_MSG_WARN([Unable to find libprocstat which is used on FreeBSD])) if test "x$have_procstat" = "xyes"; then KVM_LIBS="${KVM_LIBS} -lprocstat" fi ;; *-*-dragonfly*) CK_BACKEND="dragonfly" AC_CHECK_LIB(kvm, kvm_openfiles, have_kvm=yes, AC_MSG_ERROR([Unable to find libkvm which is needed on DragonflyBSD])) if test "x$have_kvm" = "xyes"; then KVM_LIBS="-lkvm" fi AC_CHECK_LIB(procstat, procstat_open_sysctl, have_procstat=yes, AC_MSG_WARN([Unable to find libprocstat which is used on FreeBSD])) if test "x$have_procstat" = "xyes"; then KVM_LIBS="${KVM_LIBS} -lprocstat" fi ;; *-*-netbsd*) CK_BACKEND="netbsd" AC_CHECK_LIB(kvm, kvm_openfiles, have_kvm=yes, AC_MSG_ERROR([Unable to find libkvm which is needed on NetBSD])) if test "x$have_kvm" = "xyes"; then KVM_LIBS="-lkvm" fi ;; *-*-linux*) CK_BACKEND="linux" ;; *-*-solaris*) CK_BACKEND="solaris" ;; *-*-gnu*) CK_BACKEND="gnu" ;; *) AC_MSG_ERROR([No sysdeps back-end implemented for host $host]) ;; esac AC_SUBST(KVM_LIBS) AM_CONDITIONAL(CK_COMPILE_LINUX, test x$CK_BACKEND = xlinux, [Compiling for Linux]) AM_CONDITIONAL(CK_COMPILE_FREEBSD, test x$CK_BACKEND = xfreebsd, [Compiling for FreeBSD]) AM_CONDITIONAL(CK_COMPILE_DRAGONFLY, test x$CK_BACKEND = xdragonfly, [Compiling for DragonFly]) AM_CONDITIONAL(CK_COMPILE_NETBSD, test x$CK_BACKEND = xnetbsd, [Compiling for NetBSD]) AM_CONDITIONAL(CK_COMPILE_OPENBSD, test x$CK_BACKEND = xopenbsd, [Compiling for OpenBSD]) AM_CONDITIONAL(CK_COMPILE_SOLARIS, test x$CK_BACKEND = xsolaris, [Compiling for Solaris]) AM_CONDITIONAL(CK_COMPILE_GNU, test x$CK_BACKEND = xgnu, [Compiling for GNU]) AC_SUBST(CK_BACKEND) dnl --------------------------------------------------------------------------- dnl Check for PAM dnl --------------------------------------------------------------------------- have_pam=no have_linuxpam=no AC_CHECK_LIB(pam, pam_getenv, have_pam=yes) AM_CONDITIONAL(HAVE_PAM, test x$have_pam = xyes) if test "x$have_pam" = "xyes"; then PAM_LIBS="${PAM_LIBS} -lpam" fi AC_SUBST(HAVE_PAM) AC_SUBST(PAM_LIBS) AC_CHECK_HEADERS([security/pam_modutil.h security/pam_ext.h]) AC_CHECK_LIB(pam, pam_syslog, [AC_DEFINE(HAVE_PAM_SYSLOG, [], [Define to 1 if you have the pam_syslog function])]) # Check if we should build the PAM module msg_pam_module=no AC_ARG_ENABLE(pam-module, [AS_HELP_STRING([--enable-pam-module],[build PAM module])], , enable_pam_module=no) if test "x$enable_pam_module" = "xyes"; then if test "x$have_pam" = "xno"; then AC_MSG_ERROR([--enable-pam-module requires PAM but PAM was not found]) fi AC_DEFINE(ENABLE_PAM_MODULE, [], [Set if we build PAM module]) msg_pam_module=yes fi AM_CONDITIONAL(ENABLE_PAM_MODULE, test "x$enable_pam_module" = "xyes") #Check if we can build an optional test program AC_CHECK_LIB(pam_misc, misc_conv, have_linuxpam=yes) AM_CONDITIONAL(HAVE_LINUXPAM, test "x$have_linuxpam" = "xyes") # cgroups - Using the kernel to track processes instead of the cookie XDT_CHECK_OPTIONAL_PACKAGE([CGMANAGER], [libcgmanager], [cgmanager_minimum_version], [libcgmanager], [cgmanager - Using the kernel to track processes instead of a session cookie]) # libevdev - for device management with a session controller XDT_CHECK_OPTIONAL_PACKAGE([LIBEVDEV], [libevdev], [libevdev_minimum_version], [libevdev], [libevdev - for device management with a sessions controller]) # libdrm - for device management with a session controller XDT_CHECK_OPTIONAL_PACKAGE([LIBDRM], [libdrm], [libdrm_minimum_version], [libdrm], [libdrm - for device management with a sessions controller]) # libudev - use udev as a device manager for ck-device-udev.c XDT_CHECK_OPTIONAL_PACKAGE([LIBUDEV], [libudev], [libudev_minimum_version], [libudev], [libudev - use udev as a device manager for ck-device-udev.c]) # selinux XDT_CHECK_OPTIONAL_PACKAGE([SELINUX], [libselinux], [selinux_minimum_version], [libselinux], [Security-Enhanced Linux support]) dnl ------------------------------------------------------------------------------ dnl udev-acl - apply ACLs for users with local forground sessions dnl ------------------------------------------------------------------------------ AC_ARG_ENABLE([udev-acl], AS_HELP_STRING([--enable-udev-acl], [enable local user acl permissions support @<:@default=disabled@:>@]), [], [enable_udev_acl=no]) AS_IF([test "x$enable_udev_acl" = "xyes"], [ PKG_CHECK_MODULES([UDEV_ACL], [glib-2.0 >= 2.22.0 gobject-2.0 >= 2.22.0 libudev]) AC_CHECK_LIB([acl], [acl_init], [UDEV_ACL_LIBS="$UDEV_ACL_LIBS -lacl"], AC_MSG_ERROR([libacl not found])) AC_CHECK_HEADER([acl/libacl.h], [:], AC_MSG_ERROR([libacl header not found])) UDEVDIR=`$PKG_CONFIG --variable udevdir udev` if test -z "$UDEVDIR" ; then UDEVDIR="/lib/udev" fi AC_SUBST(UDEVDIR) ]) AM_CONDITIONAL([ENABLE_UDEV_ACL], [test "x$enable_udev_acl" = "xyes"]) # DragonFly BSD supplies devattr, we already checked for the header above # make sure we can find the lib have_devattr=no AC_CHECK_LIB([devattr], [udev_device_unref], [ LIBS="$LIBS -ldevattr" have_devattr=yes ]) have_libprop=no AC_CHECK_LIB([prop], [prop_dictionary_get_cstring], [ LIBS="$LIBS -lprop" have_libprop=yes ]) use_udev=no if test ["x$LIBUDEV_FOUND" = "xyes" -a "x$LIBDRM_FOUND" = "xyes"]; then use_udev=yes fi if test ["$have_devattr" = "yes" -a "$have_libprop" = "yes"]; then use_udev=yes fi # we need both udev/devattr and libdrm for udev support AS_IF(test ["$use_udev" = "yes"], [ AC_DEFINE([USE_UDEV_BACKEND], [1], [Define if we meet requirements to use the udev backend]) ]) AM_CONDITIONAL([USE_UDEV_BACKEND], [test ["$use_udev" = "yes"]]) AC_SUBST(USE_UDEV_BACKEND) dnl --------------------------------------------------------------------------- dnl - Install directory for PAM security module dnl --------------------------------------------------------------------------- AC_ARG_WITH(pam-module-dir, [AS_HELP_STRING([--with-pam-module-dir=],[directory to install PAM security module])]) if ! test -z "$with_pam_module_dir"; then PAM_MODULE_DIR="$with_pam_module_dir" else PAM_MODULE_DIR="/lib/security" fi AC_SUBST(PAM_MODULE_DIR) dnl --------------------------------------------------------------------------- dnl - Install directory for xinitrc file dnl --------------------------------------------------------------------------- AC_ARG_WITH(xinitrc-dir, [AS_HELP_STRING([--with-xinitrc-dir=],[directory to install Xsession.d script for ck-launch-session])]) if ! test -z "$with_xinitrc_dir"; then XINITRC_DIR="$with_xinitrc_dir" else XINITRC_DIR="$sysconfdir/X11/xinit/xinitrc.d" fi AC_SUBST(XINITRC_DIR) dnl --------------------------------------------------------------------------- dnl - DocBook Documentation dnl --------------------------------------------------------------------------- AC_ARG_ENABLE(docbook-docs, [AS_HELP_STRING([--enable-docbook-docs],[build documentation (requires xmlto)])], enable_docbook_docs=$enableval,enable_docbook_docs=no) AC_PATH_PROG(XMLTO, xmlto, no) AC_MSG_CHECKING([whether to build DocBook documentation]) if test x$XMLTO = xno ; then have_docbook=no else have_docbook=yes fi if test x$enable_docbook_docs = xauto ; then if test x$have_docbook = xno ; then enable_docbook_docs=no else enable_docbook_docs=yes fi fi if test x$enable_docbook_docs = xyes; then if test x$have_docbook = xno; then AC_MSG_ERROR([Building DocBook docs explicitly required, but DocBook not found]) fi fi AM_CONDITIONAL(DOCBOOK_DOCS_ENABLED, test x$enable_docbook_docs = xyes) AC_MSG_RESULT(yes) AC_ARG_VAR([XMLTO],[Define/override the xmlto location.]) AC_ARG_VAR([XMLTO_FLAGS],[Define/override xmlto options, like --skip-validation.]) dnl --------------------------------------------------------------------------- dnl Check for xsltproc dnl --------------------------------------------------------------------------- AC_PATH_PROG([XSLTPROC], [xsltproc]) # check for gtk-doc m4_ifdef([GTK_DOC_CHECK], [ GTK_DOC_CHECK([1.14],[--flavour no-tmpl]) ],[ AM_CONDITIONAL([ENABLE_GTK_DOC], false) ]) dnl --------------------------------------------------------------------------- dnl check for inotify dnl --------------------------------------------------------------------------- enable_inotify=no AC_CHECK_FUNC(inotify_init, [AC_CHECK_HEADER([sys/inotify.h], [enable_inotify=yes], [])], []) AM_CONDITIONAL(ENABLE_INOTIFY, test "x$enable_inotify" = "xyes") if test "x$enable_inotify" = "xyes" ; then AC_DEFINE(ENABLE_INOTIFY, [], [Define if we have inotify]) fi dnl --------------------------------------------------------------------------- dnl check for RBAC dnl --------------------------------------------------------------------------- msg_rbac_shutdown=no AC_ARG_ENABLE(rbac-shutdown, [AS_HELP_STRING([--enable-rbac-shutdown=],[Build with RBAC support specifying shutdown/reboot RBAC authentication key])], enable_rbac_shutdown=$enableval,enable_rbac_shutdown=no) if test "x$enable_rbac_shutdown" != "xno"; then RBAC_LIBS="-lsecdb -lsocket -lnsl" AC_DEFINE(ENABLE_RBAC_SHUTDOWN, [], [Set if we build with RBAC support]) AC_DEFINE_UNQUOTED(RBAC_SHUTDOWN_KEY, "$enable_rbac_shutdown", [Set if we build with RBAC support]) msg_rbac_shutdown="yes, using key $enable_rbac_shutdown" fi AC_SUBST(RBAC_LIBS) # # Enable Tests # AC_ARG_ENABLE(tests, [AS_HELP_STRING([--enable-tests],[enable validation test framework @<:@default=@<:@disabled@:>@@:>@])], enable_tests=yes, enable_tests=no) AC_MSG_CHECKING([whether to build the validation test framework]) AM_CONDITIONAL(BUILD_TESTS, test "x$enable_tests" = "xyes") AC_MSG_RESULT($enable_tests) dnl --------------------------------------------------------------------------- dnl Finish dnl --------------------------------------------------------------------------- # Check for introspection for libck2 GOBJECT_INTROSPECTION_CHECK([1.30.0]) # Enable Debug XDT_FEATURE_DEBUG # Check for linker optimizations XDT_FEATURE_LINKER_OPTS() # Flags AC_SUBST(CK2_LIBS) AC_SUBST(TOOLS_LIBS) AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) # systemd AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), [], [with_systemdsystemunitdir=no]) AS_IF([test "x$with_systemdsystemunitdir" != "xno"], [ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])]) AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != "xno"]) # Misc version info VERSION_MESSAGE="${VERSION}" COPYRIGHT_MESSAGE="Copyright © ${COPYRIGHT_YEARS} the ConsoleKit2 team" AC_DEFINE_UNQUOTED(VERSION_MESSAGE, "${VERSION_MESSAGE}", [Simple version string]) AC_DEFINE_UNQUOTED(COPYRIGHT_MESSAGE, "${COPYRIGHT_MESSAGE}", [Copyright string]) AC_DEFINE_UNQUOTED(COPYRIGHT_YEARS, "${COPYRIGHT_YEARS}", [The copyright years]) AC_DEFINE_UNQUOTED(PACKAGE_VERSION_MAJOR,${VERSION_MAJOR}, [version major number]) AC_DEFINE_UNQUOTED(PACKAGE_VERSION_MINOR,${VERSION_MINOR}, [version minor number]) AC_DEFINE_UNQUOTED(PACKAGE_VERSION_REVISION,${VERSION_REVISION}, [version revision number]) AC_DEFINE_UNQUOTED(PACKAGE, "ConsoleKit2", [The name of this package]) AC_SUBST(COPYRIGHT_MESSAGE) AC_SUBST(VERSION_MESSAGE) AC_SUBST(VERSION_MAJOR) AC_SUBST(VERSION_MINOR) AC_SUBST(VERSION_REVISION) AC_SUBST(COPYRIGHT_YEARS) AC_SUBST(PACKAGE) # Files AC_CONFIG_FILES([ Makefile src/Makefile tools/70-udev-acl.rules tools/71-udev-seat.rules tools/Makefile tools/linux/Makefile tools/freebsd/Makefile tools/netbsd/Makefile tools/openbsd/Makefile tools/solaris/Makefile data/Makefile doc/Makefile doc/console-kit-daemon.1m doc/dbus/ConsoleKit.xml doc/dbus/Makefile doc/libconsolekit/Makefile libconsolekit/Makefile libconsolekit/libconsolekit.pc libck-connector/Makefile libck-connector/ck-connector.pc pam-ck-connector/Makefile po/Makefile.in ]) AC_OUTPUT echo " ConsoleKit $VERSION ======================== prefix: ${prefix} exec_prefix: ${exec_prefix} libdir: ${libdir} bindir: ${bindir} sbindir: ${sbindir} sysconfdir: ${sysconfdir} localstatedir: ${localstatedir} rundir: ${RUNDIR} datadir: ${datadir} source code location: ${srcdir} compiler: ${CC} cflags: ${CFLAGS} Debugging support: $enable_debug build tests: ${enable_tests} Maintainer mode: ${USE_MAINTAINER_MODE} dbus-1 system.d dir: ${DBUS_SYS_DIR} Build backend: ${CK_BACKEND} PAM module dir: ${PAM_MODULE_DIR} Build PAM module: ${msg_pam_module} Build udev-acl: ${enable_udev_acl}" if test x"$LIBUDEV_FOUND" = x"yes"; then echo " udev support yes" else echo " udev support no" fi if test x"$CGMANAGER_FOUND" = x"yes"; then echo " cgroup support yes" else echo " cgroup support no" fi if test x"$LIBEVDEV_FOUND" = x"yes"; then echo " libevdev support yes" else echo " libevdev support no" fi if test x"$LIBDRM_FOUND" = x"yes"; then echo " libdrm support yes" else echo " libdrm support no" fi if test "$use_udev" = "yes"; then echo " session controller udev" else echo " session controller none" fi if test x"$SELINUX_FOUND" = x"yes"; then echo " SELinux support: yes" else echo " SELinux support: no" fi echo " Build docs: ${enable_docbook_docs} xinitrc dir: ${XINITRC_DIR}" if test x"$POLKIT_FOUND" = x"yes"; then echo " PolicyKit support yes" else echo " PolicyKit support no" fi echo " RBAC (Solaris) support: ${msg_rbac_shutdown}" if test x"$POLKIT_FOUND" != x"yes" -a x${msg_rbac_shutdown} = xno; then echo "WARNING: PolicyKit and RBAC are disabled. You need to manually edit the ConsoleKit.conf" echo " file to lock down the service. Failure to do so may be" echo " a huge SECURITY HOLE. I repeat: YOU NEED TO EDIT THE FILE" echo " ConsoleKit.conf to match your distro/site to avoid NASTY SECURITY HOLES." echo "" fi consolekit2-1.2.6/data/000077500000000000000000000000001446640754400147035ustar00rootroot00000000000000consolekit2-1.2.6/data/.gitignore000066400000000000000000000003161446640754400166730ustar00rootroot00000000000000Makefile Makefile.in ConsoleKit org.freedesktop.ConsoleKit.service console-kit-daemon.service console-kit-log-system-start.service console-kit-log-system-stop.service console-kit-log-system-restart.service consolekit2-1.2.6/data/00-primary.seat000066400000000000000000000001001446640754400174500ustar00rootroot00000000000000[Seat Entry] Version=1.0 Name=Primary seat Hidden=false Devices=consolekit2-1.2.6/data/90-consolekit.in000066400000000000000000000017521446640754400176400ustar00rootroot00000000000000# -*- sh -*- # Xsession.d script for ck-launch-session. # # # This file is sourced by Xsession(5), not executed. @CK_LAUNCH_SESSION@ is_on_console() { session=$(dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.GetCurrentSession \ | grep path | awk '{print $3}' | sed s/\"//g) x11_display=$(dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ $session org.freedesktop.ConsoleKit.Session.GetX11Display \ | grep string | awk '{print $2}' | sed s/\"//g) if [ -z "$x11_display" ] ; then return 0 else return 1 fi } # gdm already creates a CK session for us, so do not run the expensive D-Bus # calls if we have $GDMSESSION if [ -z "$GDMSESSION" ] && [ -x "$CK_LAUNCH_SESSION" ] && \ ( [ -z "$XDG_SESSION_COOKIE" ] || is_on_console ) ; then STARTUP="$CK_LAUNCH_SESSION $STARTUP" fi consolekit2-1.2.6/data/ConsoleKit.conf000066400000000000000000000274101446640754400176300ustar00rootroot00000000000000 consolekit2-1.2.6/data/Makefile.am000066400000000000000000000110671446640754400167440ustar00rootroot00000000000000NULL = BUILT_SOURCES = dbusconfdir = $(DBUS_SYS_DIR) dbusconf_DATA = ConsoleKit.conf seatdir = $(sysconfdir)/ConsoleKit/seats.d seat_DATA = 00-primary.seat if HAVE_POLKIT polkit_policydir = $(datadir)/polkit-1/actions dist_polkit_policy_DATA = \ org.freedesktop.consolekit.policy \ $(NULL) endif servicedir = $(datadir)/dbus-1/system-services service_in_files = org.freedesktop.ConsoleKit.service.in service_DATA = $(service_in_files:.service.in=.service) $(service_DATA): $(service_in_files) Makefile $(edit) $< >$@ edit = sed \ -e 's|@sbindir[@]|$(sbindir)|g' \ -e 's|@sysconfdir[@]|$(sysconfdir)|g' \ -e 's|@localstatedir[@]|$(localstatedir)|g' \ -e 's|@CONSOLE_KIT_PID_FILE[@]|$(CONSOLE_KIT_PID_FILE)|g' if HAVE_SYSTEMD systemdsystemunit_DATA = \ console-kit-daemon.service \ console-kit-log-system-start.service \ console-kit-log-system-stop.service \ console-kit-log-system-restart.service console-kit-daemon.service: console-kit-daemon.service.in $(edit) $< >$@ console-kit-log-system-start.service: console-kit-log-system-start.service.in $(edit) $< >$@ console-kit-log-system-stop.service: console-kit-log-system-stop.service.in $(edit) $< >$@ console-kit-log-system-restart.service: console-kit-log-system-restart.service.in $(edit) $< >$@ install-data-hook: $(MKDIR_P) -m 755 \ $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants \ $(DESTDIR)$(systemdsystemunitdir)/halt.target.wants \ $(DESTDIR)$(systemdsystemunitdir)/poweroff.target.wants \ $(DESTDIR)$(systemdsystemunitdir)/reboot.target.wants \ $(DESTDIR)$(systemdsystemunitdir)/kexec.target.wants ( cd $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants && \ rm -f console-kit-log-system-start.service && \ $(LN_S) ../console-kit-log-system-start.service ) ( cd $(DESTDIR)$(systemdsystemunitdir)/halt.target.wants && \ rm -f console-kit-log-system-stop.service && \ $(LN_S) ../console-kit-log-system-stop.service ) ( cd $(DESTDIR)$(systemdsystemunitdir)/poweroff.target.wants && \ rm -f console-kit-log-system-stop.service && \ $(LN_S) ../console-kit-log-system-stop.service ) ( cd $(DESTDIR)$(systemdsystemunitdir)/reboot.target.wants && \ rm -f console-kit-log-system-restart.service && \ $(LN_S) ../console-kit-log-system-restart.service ) ( cd $(DESTDIR)$(systemdsystemunitdir)/kexec.target.wants && \ rm -f console-kit-log-system-restart.service && \ $(LN_S) ../console-kit-log-system-restart.service ) edit += \ -e 's|@SystemdService[@]|SystemdService=console-kit-daemon.service|g' else edit += \ -e 's|@SystemdService[@]||g' endif install-data-local: install-logrotate install-90-consolekit $(MKDIR_P) $(DESTDIR)$(localstatedir)/log/ConsoleKit/ uninstall-local:: uninstall-logrotate uninstall-90-consolekit rmdir --ignore-fail-on-non-empty $(DESTDIR)$(localstatedir)/log/ConsoleKit/ LOGROTATE_CONFS = consolekit.logrotate XINITRC_CONFS = 90-consolekit BUILT_SOURCES += \ $(LOGROTATE_CONFS) \ $(XINITRC_CONFS) \ $(NULL) consolekit.logrotate: consolekit.logrotate.in sed \ -e 's![@]localstatedir[@]!$(localstatedir)!g' \ < $< > $@-t mv $@-t $@ 90-consolekit: 90-consolekit.in sed \ -e 's![@]CK_LAUNCH_SESSION[@]!CK_LAUNCH_SESSION=$(bindir)/ck-launch-session!g' \ < $< > $@-t mv $@-t $@ install-logrotate: $(LOGROTATE_CONFS) $(MKDIR_P) $(DESTDIR)$(localstatedir)/log/ConsoleKit/ \ $(DESTDIR)$(sysconfdir)/logrotate.d/ $(INSTALL_DATA) consolekit.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/consolekit install-90-consolekit: $(XINITRC_CONFS) $(MKDIR_P) $(DESTDIR)$(XINITRC_DIR)/ $(INSTALL_SCRIPT) 90-consolekit $(DESTDIR)$(XINITRC_DIR) uninstall-logrotate: rm -f $(DESTDIR)$(sysconfdir)/logrotate.d/consolekit uninstall-90-consolekit: rm -f $(DESTDIR)$(XINITRC_DIR)/90-consolekit EXTRA_DIST = \ ck-log-system-restart \ ck-log-system-start \ ck-log-system-stop \ $(dbusconf_DATA) \ $(seat_DATA) \ $(service_in_files) \ console-kit-daemon.service.in \ console-kit-log-system-start.service.in \ console-kit-log-system-stop.service.in \ console-kit-log-system-restart.service.in \ 90-consolekit.in \ consolekit.logrotate.in \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in CLEANFILES = \ $(service_DATA) \ $(BUILT_SOURCES) \ console-kit-daemon.service \ console-kit-log-system-start.service \ console-kit-log-system-stop.service \ console-kit-log-system-restart.service consolekit2-1.2.6/data/ck-log-system-restart000066400000000000000000000002221446640754400210020ustar00rootroot00000000000000# Upstart event # ck-log-system-restart - write system restart to log # start on runlevel 6 console output exec /usr/sbin/ck-log-system-restart consolekit2-1.2.6/data/ck-log-system-start000066400000000000000000000002151446640754400204550ustar00rootroot00000000000000# Upstart event # ck-log-system-start - write system start to log # start on stopped rcS console output exec /usr/sbin/ck-log-system-start consolekit2-1.2.6/data/ck-log-system-stop000066400000000000000000000002111446640754400203010ustar00rootroot00000000000000# Upstart event # ck-log-system-stop - write system stop to log # start on runlevel 0 console output exec /usr/sbin/ck-log-system-stop consolekit2-1.2.6/data/console-kit-daemon.service.in000066400000000000000000000006601446640754400223640ustar00rootroot00000000000000[Unit] Description=Console Manager After=syslog.target [Service] Type=dbus BusName=org.freedesktop.ConsoleKit ExecStart=@sbindir@/console-kit-daemon --no-daemon [Install] # We pull this in by graphical.target instead of waiting for the bus # activation, to speed things up a little: gdm uses this anyway so it is nice # if it is already around when gdm wants to use it and doesn't have to wait for # it. WantedBy=graphical.target consolekit2-1.2.6/data/console-kit-log-system-restart.service.in000066400000000000000000000003331446640754400247030ustar00rootroot00000000000000[Unit] Description=Console System Reboot Logging DefaultDependencies=no After=sysinit.target console-kit-log-system-start.service Before=shutdown.target [Service] Type=oneshot ExecStart=@sbindir@/ck-log-system-restart consolekit2-1.2.6/data/console-kit-log-system-start.service.in000066400000000000000000000003111446640754400243500ustar00rootroot00000000000000[Unit] Description=Console System Startup Logging DefaultDependencies=no After=sysinit.target Before=shutdown.target [Service] Type=oneshot ExecStart=@sbindir@/ck-log-system-start RemainAfterExit=yes consolekit2-1.2.6/data/console-kit-log-system-stop.service.in000066400000000000000000000003321446640754400242030ustar00rootroot00000000000000[Unit] Description=Console System Shutdown Logging DefaultDependencies=no After=sysinit.target console-kit-log-system-start.service Before=shutdown.target [Service] Type=oneshot ExecStart=@sbindir@/ck-log-system-stop consolekit2-1.2.6/data/consolekit.logrotate.in000066400000000000000000000002221446640754400214000ustar00rootroot00000000000000@localstatedir@/log/ConsoleKit/history { monthly rotate 6 delaycompress compress notifempty missingok } consolekit2-1.2.6/data/org.freedesktop.ConsoleKit.service.in000066400000000000000000000001711446640754400240430ustar00rootroot00000000000000[D-BUS Service] Name=org.freedesktop.ConsoleKit Exec=@sbindir@/console-kit-daemon --no-daemon User=root @SystemdService@ consolekit2-1.2.6/data/org.freedesktop.consolekit.policy000066400000000000000000000073431446640754400234050ustar00rootroot00000000000000 Stop the system System policy prevents stopping the system no yes Stop the system when multiple users are logged in System policy prevents stopping the system when other users are logged in no auth_admin_keep Restart the system System policy prevents restarting the system no yes Restart the system when multiple users are logged in System policy prevents restarting the system when other users are logged in no auth_admin_keep Suspend the system System policy prevents suspending the system no yes Suspend the system when multiple users are logged in System policy prevents suspending the system when other users are logged in no auth_admin_keep Hibernate the system System policy prevents hibernating the system no yes Hibernate the system when multiple users are logged in System policy prevents hibernating the system when other users are logged in no auth_admin_keep Hybrid sleep the system (sleep + hibernate) System policy prevents hybrid sleeping the system no yes Hybrid sleep the system (sleep + hibernate) when multiple users are logged in System policy prevents hybrid sleeping the system when other users are logged in no auth_admin_keep consolekit2-1.2.6/doc/000077500000000000000000000000001446640754400145375ustar00rootroot00000000000000consolekit2-1.2.6/doc/.gitignore000066400000000000000000000000341446640754400165240ustar00rootroot00000000000000Makefile Makefile.in *.o *~ consolekit2-1.2.6/doc/Makefile.am000066400000000000000000000003311446640754400165700ustar00rootroot00000000000000SUBDIRS = dbus libconsolekit manpagedir = $(mandir)/man1 manpage_DATA = \ ck-history.1 \ ck-launch-session.1 \ ck-list-sessions.1 \ console-kit-daemon.1m EXTRA_DIST = \ $(manpage_DATA) consolekit2-1.2.6/doc/ck-history.1000066400000000000000000000050561446640754400167230ustar00rootroot00000000000000'\" te .TH ck-history 1 "22 Oct 2009" "SunOS 5.11" "User Commands" .SH "NAME" ck-history \- ConsoleKit history .SH "SYNOPSIS" .PP \fBck-history\fR [-\fB-frequent\fR] [-\fB-help\fR] [-\fB-last\fR] [-\fB-last-compat\fR] [-\fB-log\fR] [-\fB-seat=\fIseat\fR\fR] [-\fB-session-type=\fItype\fR\fR] [-\fB-user=\fIuser\fR\fR] [-\fB-version\fR] .SH "DESCRIPTION" .PP \fBck-history\fR is a utility that provides information from the ConsoleKit database about what users have logged into the system\&. It supports options to specify whether to provide information about users who have logged in most frequently or most recently\&. .PP The \fBck-history\fR utility is used by \fBgdm\fR(1m) when the GDM Face Browser is enabled to display users in the order of frequency\&. .SH "OPTIONS" .PP The following options are supported: .sp .ne 2 .mk \fB-\fB-frequent\fR\fR .in +32n .rt Show listing of logged-in users in the most frequent order\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fBh\fR, -\fB-help\fR\fR .in +32n .rt Display detailed usage message\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fB-last\fR\fR .in +32n .rt Show listing of all user logins since logging began in the most-recent order.\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fB-last-compat\fR\fR .in +32n .rt Show listing of logged-in users in the most-recent order\&. The output is displayed in \fBlast\fR(1) compatible format\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fB-log\fR\fR .in +32n .rt Show full ConsoleKit event log\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fBs\fR, -\fB-seat=\fIseat\fR\fR\fR .in +32n .rt Show entries for the specified \fIseat\fR\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fBt\fR, -\fB-session-type=\fItype\fR\fR\fR .in +32n .rt Show entries for the specified session \fItype\fR\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fBu\fR, -\fB-user=\fIuser\fR\fR\fR .in +32n .rt Show entries for the specified \fIuser\fR\&. .sp .sp 1 .in -32n .sp .ne 2 .mk \fB-\fBV\fR, -\fB-version\fR\fR .in +32n .rt Display the version of the \fBck-history\fR application\&. .sp .sp 1 .in -32n .SH "EXAMPLES" .PP \fBExample 1: Show most frequently logged in users\fR .PP .PP .nf example% \fBck-history -\fB-frequent\fR\fR .fi .PP \fBExample 2: Show the entire ConsoleKit log\&.\fR .PP .PP .nf example% \fBck-history -\fB-log\fR\fR .fi .SH "SEE ALSO" .PP \fBck-launch-session\fR(1), \fBck-list-sessions\fR(1), \fBconsole-kit-daemon\fR(1m) .SH "NOTES" .PP Written by Brian Cameron, Sun Microsystems Inc\&., 2009\&. Copyright (c) 2009 by Sun Microsystems, Inc\&. ...\" created by instant / solbook-to-man, Sat 24 Oct 2009, 14:10 ...\" LSARC 2009/432 ConsoleKit consolekit2-1.2.6/doc/ck-launch-session.1000066400000000000000000000023221446640754400201460ustar00rootroot00000000000000'\" te .TH ck-launch-session 1 "22 Oct 2009" "SunOS 5.11" "User Commands" .SH "NAME" ck-launch-session \- Utility to start a ConsoleKit session from a shell script .SH "SYNOPSIS" .PP \fBck-launch-session\fR \fB\fIcommand\fR\fR .SH "DESCRIPTION" .PP \fBck-launch-session\fR is a utility for starting a command in its own ConsoleKit session, however the command is optional. If not specified it launches a shell.\&. This would be useful if a user wanted to start their own session via a \fBstartx\fR script and have it registered with ConsoleKit, for example\&. .SH "OPERANDS" .PP The following operands are supported: .sp .ne 2 .mk \fB\fB\fIcommand\fR\fR\fR .in +16n .rt Start the specified \fIcommand\fR in its own ConsoleKit session\&. .sp .sp 1 .in -16n .SH "EXAMPLES" .PP \fBExample 1: Launch the \fBstartx\fR command in its own ConsoleKit session\fR .PP .PP .nf example% \fBck-launch-session \fBstartx\fR\fR .fi .SH "SEE ALSO" .PP \fBck-history\fR(1), \fBck-list-sessions\fR(1), \fBconsole-kit-daemon\fR(1m) .SH "NOTES" .PP Written by Brian Cameron, Sun Microsystems Inc\&., 2009\&. Copyright (c) 2009 by Sun Microsystems, Inc\&. ...\" created by instant / solbook-to-man, Sat 24 Oct 2009, 14:10 ...\" LSARC 2009/432 ConsoleKit consolekit2-1.2.6/doc/ck-list-sessions.1000066400000000000000000000146121446640754400200370ustar00rootroot00000000000000'\" te .TH ck-list-sessions 1 "22 Oct 2009" "SunOS 5.11" "User Commands" .SH "NAME" ck-list-sessions \- Show ConsoleKit Session Information .SH "SYNOPSIS" .PP \fBck-list-sessions\fR [-\fB-all\fR] [-\fB-format=\fIformat\fR\fR] [-\fB-help\fR] [-\fB-version\fR] .SH "DESCRIPTION" .PP \fBck-list-sessions\fR is a utility that displays information from the ConsoleKit database\&. By default, only open sessions are shown\&. The -\fB-all\fR option can be used to display all existing sessions on the system\&. \fBck-list-sessions\fR returns information about each ConsoleKit session\&. Users can specify which properties to display via the -\fB-format\fR option\&. .PP The following properties can be displayed for each session: .SH "OPTIONS" .PP The following options are supported: .sp .ne 2 .mk \fB-\fBa\fR, -\fB-all\fR\fR .in +24n .rt Show all ConsoleKit sessions\&. If this option is not provided, only open sessions are shown\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fB-\fBf\fR, -\fB-format=\fIformat\fR\fR\fR .in +24n .rt Display information using the specified \fIformat\fR\&. The \fIformat\fR value is a list of properties to display separated by commas\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fB-\fBh\fR, -\fB-help\fR\fR .in +24n .rt Display detailed usage message\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fB-\fBV\fR, -\fB-version\fR\fR .in +24n .rt Display the version of the \fBck-list-sessions\fR application\&. .sp .sp 1 .in -24n .SH "EXTENDED DESCRIPTION" .SS "ConsoleKit session properties" .PP For each session, the following session properties are displayed: .sp .ne 2 .mk \fBunix-user\fR .in +24n .rt The user id value associated with the session\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBrealname\fR .in +24n .rt The name of the user associated with the session\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBseat\fR .in +24n .rt The ID for the ConsoleKit Seat associated with the session\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBsession-type\fR .in +24n .rt The ConsoleKit session type\&. This value is set by the process that opens the session and will usually be set to the display protocol used, i\&.e\&. x11, wayland, tty, mir, or unspecified\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBsession-class\fR .in +24n .rt The ConsoleKit session class\&. This value is set by the process that opens the session and will usually be set to user for normal sessions or greeter, lock-screen, or background for special purpose sessions\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBsession-state\fR .in +24n .rt The current state of the ConsoleKit session\&. It is managed by ConsoleKit and will either return online, active, or closing\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBdisplay-type\fR .in +24n .rt The ConsoleKit display type\&. This value is specified by the "DisplayTemplate" key in the ConsoleKit session configuration file associated with this session\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBopen\fR .in +24n .rt The value is "TRUE" if the session is open, and "FALSE" otherwise\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBactive\fR .in +24n .rt The value is "TRUE" if the session is active on the seat to which it is attached, and "FALSE" otherwise\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBx11-display\fR .in +24n .rt The value of the X11 DISPLAY environment variable for this session if one is present\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBx11-display-device\fR .in +24n .rt The value of the display device that the X11 display for the session is connected to\&. If there is no x11-display set, then this value is undefined\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBdisplay-device\fR .in +24n .rt The display device associated with the session\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBremote-host\fR .in +24n .rt If the session is not local, the value is the host name associated with the session\&. If the session is local, the value is empty\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBVTNr\fR .in +24n .rt The virtual terminal the ConsoleKit session is on, if any\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBis-local\fR .in +24n .rt The value is "TRUE" if the session is local, and "FALSE" if remote\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBon-since\fR .in +24n .rt An ISO 8601 date-time string that corresponds to the time the session started\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBlogin-session-id\fR .in +24n .rt The value of the login session ID that the underlying system uses to enforce session boundaries\&. If there is no login session ID set then this value is an empty string\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fBidle-since-hint\fR .in +24n .rt An ISO 8601 date-time string that corresponds to the time of the last change of the idle-hint\&. This is a hint used to indicate that the session may be idle\&. For sessions with a x11-display set (ie\&. graphical sessions), it is up to each session to delegate the responsibility for updating this value\&. Typically, the screensaver will set this\&. .sp However, for non-graphical sessions with a display-device set the Session object itself will periodically update this value based on the activity detected on the display-device itself\&. .sp This should not be considered authoritative\&. .sp .sp 1 .in -24n .SH "EXAMPLES" .PP \fBExample 1: Show running sessions\&.\fR .PP .PP .nf example% \fBck-list-sessions\fR .fi .PP This command would generate output like the following for each session: .PP .PP .nf SessionSeat1Local: unix-user = \&'50\&' realname = \&'GDM Reserved UID\&' seat = \&'Seat1\&' session-type = \&'LoginWindow\&' display-type = \&'Local\&' open = \&'TRUE\&' active = \&'TRUE\&' x11-display = \&':0\&' x11-display-device = \&'/dev/console\&' display-device = \&'/dev/console\&' remote-host-name = \&'\&' is-local = \&'TRUE\&' on-since = \&'2009-08-11T06:46:42\&.941134Z\&' login-session-id = \&'\&' idle-since-hint = \&'\&' .fi .PP \fBExample 2: Show only the session-id, unix-user, and display-type properties\&.\fR .PP .PP .nf example% \fBck-list-sessions -\fB-format="session-id,unix-user,display-type"\fR\fR .fi .PP This command would generate output like the following for each session: .PP .PP .nf SessionSeat1Local 50 Local .fi .SH "SEE ALSO" .PP \fBck-history\fR(1), \fBck-launch-session\fR(1), \fBconsole-kit-daemon\fR(1m) .SH "NOTES" .PP Written by Brian Cameron, Sun Microsystems Inc\&., 2009\&. Copyright (c) 2009 by Sun Microsystems, Inc\&. ...\" created by instant / solbook-to-man, Sat 24 Oct 2009, 14:10 ...\" LSARC 2009/432 ConsoleKit consolekit2-1.2.6/doc/console-kit-daemon.1m.in000066400000000000000000000272441446640754400211040ustar00rootroot00000000000000'\" te .TH console-kit-daemon 1m "24 Oct 2009" "SunOS 5.11" "Maintenance Commands" .SH "NAME" console-kit-daemon \- ConsoleKit daemon .SH "SYNOPSIS" .PP \fBconsole-kit-daemon\fR [-\fB-debug\fR] [-\fB-help\fR] [-\fB-no-daemon\fR] [-\fB-timed-exit\fR] .SH "DESCRIPTION" .PP \fBconsole-kit-daemon\fR is a service for defining and tracking users, login sessions and seats\&. It provides interfaces for managing switching sessions and session migration when using mechanisms such as Virtual Terminals (VT)\&. ConsoleKit provides a number of interfaces to specify what displays are managed by the display manager, and how\&. .PP ConsoleKit maintains a database of which users are logged into the system\&. ConsoleKit groups sessions by seats which represent a set of hardware (usually a keyboard and mouse)\&. Other process communicate with ConsoleKit via D-Bus\&. .PP One session leader process is responsible for asking \fBconsole-kit-daemon\fR to open a new session\&. In the typical case, the session leader would be a ConsoleKit enabled display manager, such as GDM\&. This leader makes a connection to the D-Bus system bus and asks \fBconsole-kit-daemon\fR to open a session when needed\&. .PP If the operation succeeds, \fBconsole-kit-daemon\fR will return a cookie to the session leader\&. The session leader should store this variable in the environment as XDG_SESSION_COOKIE so that it may be shared with its child processes\&. The environment variable contains the UUID used to tie processes to a session\&. .PP At this point the session will be registered with ConsoleKit and a particular set of information about the session will be stored along with it\&. .PP The Session will remain open until the Session Leader disconnects from the D-Bus system bus\&. The session will be removed from its seat, and deregistered\&. .PP Various other programs need to know information about running user sessions, such as the Fast User Switch Applet and other mechanisms for switching the console to use a different VT display\&. Such programs make use of ConsoleKit interfaces to determine if user switching is supported and to manage the switching of different sessions on the same seat\&. .PP ConsoleKit provides a pam_ck_connector so that non-graphical logins (e\&.g\&. telnet, ssh, etc\&.) are registered with ConsoleKit\&. This functionality works if this PAM module is enabled in the \fBpam\&.conf\fR(4) configuration\&. Thus ConsoleKit can be used as a utmp/wtmp replacement since it stores a superset of the information as in the utmp/wtmp database\&. .PP The ConsoleKit database is stored in the file \fB@RUNDIR@/ConsoleKit/database\fR\&. It stores information about active Seats, Sessions, and the current SessionLeader\&. .SH "OPTIONS" .PP The following options are supported: .sp .ne 2 .mk \fB-\fB-debug\fR\fR .in +24n .rt Enable debug output\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fB-\fBh\fR, -\fB-help\fR\fR .in +24n .rt Display detailed usage message\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fB-\fB-no-daemon\fR\fR .in +24n .rt Avoid starting \fBconsole-kit-daemon\fR as a daemon\&. Useful for debugging\&. .sp .sp 1 .in -24n .sp .ne 2 .mk \fB-\fB-timed-exit\fR\fR .in +24n .rt Exit after 30 seconds\&. Useful for debugging\&. .sp .sp 1 .in -24n .SH "ENVIRONMENT VARIABLES" .PP See \fBenviron\fR(5) for descriptions of environment variables\&. .sp .ne 2 .mk \fB\fBDISPLAY\fR\fR .sp .6 .in +4 This environment variable corresponds to the Xserver display value associated with the ConsoleKit session\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBXDG_SESSION_COOKIE\fR\fR .sp .6 .in +4 ConsoleKit provides this environment variable to the session leader\&. The session leader is expected to ensure this is set for the session process started\&. It contains a UUID used to tie the processes to the session\&. This is used to support user switching on displays that support it (currently only graphical VT displays on the console)\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBXDG_RUNTIME_DIR\fR\fR .sp .6 .in +4 The XDG_RUNTIME_DIR defines the base directory to which user-specific files and objects should be stored. The XDG_RUNTIME_DIR is the same for all sessions of the same user and will be automatically removed once the last session of the user is closed. .sp .sp 1 .in -4 .PP The following environment variables are set when \fBconsole-kit-daemon\fR runs the \fBrun-seat\&.d\fR scripts\&. These values correspond to those values returned by the \fBck-list-session\fR(1) utility\&. .sp .ne 2 .mk \fB\fBCK_SESSION_SEAT_ID\fR\fR .sp .6 .in +4 The seat ID associated with the session\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_SEAT_UID\fR\fR .sp .6 .in +4 The user id associated with the session .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_DISPLAY_DEVICE\fR\fR .sp .6 .in +4 The display device associated with the session\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_X11_DISPLAY_DEVICE\fR\fR .sp .6 .in +4 The value of the display device that the X11 display for the session is connected to\&. If there is no x11-display set, then this value is undefined\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_X11_DISPLAY\fR\fR .sp .6 .in +4 The value of the X11 DISPLAY environment variable for this session if one is present\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_REMOTE_HOST_NAME\fR\fR .sp .6 .in +4 If the session is not local, the value is the host name associated with the session\&. If the session is local, the value is empty\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_IS_ACTIVE\fR\fR .sp .6 .in +4 The value is "TRUE" if the session is active on the seat to which it is attached, and "FALSE" otherwise\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_IS_LOCAL\fR\fR .sp .6 .in +4 The value is "TRUE" if the session is local, and "FALSE" if remote\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fB\fBCK_SESSION_IS_DYNAMIC\fR\fR .sp .6 .in +4 The value is "TRUE" if the session was started with \fBck-seat-tool\fR, and "FALSE" otherwise\&. .sp .sp 1 .in -4 .SH "EXTENDED DESCRIPTION" .SS "ConsoleKit Seat Configuration" .PP ConsoleKit seat configuration files are located in the /etc/ConsoleKit/seats\&.d directory\&. Each seat configuration file ends with the \fB\&.seat\fR suffix\&. ConsoleKit provides a default seat file named \fB00-primary\&.seat\fR\&. Additional seat configuration files may be added\&. These files are in standard INI format\&. .PP The settings below are in "group/key=\fIdefault_value\fR" format, and show the default values of the \fB00-primary\&.seat\fR file\&. For example, to specify a different "Seat Entry/Name" value, you would modify the this file so it contains these lines: .PP .nf [Seat Entry] [\&.\&.\&.] Name=Customized seat name .fi .PP The following keys are supported for configuring ConsoleKit seats: .sp .ne 2 .mk \fBSeat Entry/Version=1\&.0\fR .sp .6 .in +4 Version number of the seat file\&. This specifies the version number of the configuration file format used\&. Currently only the value "1\&.0" is supported\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSeat Entry/Name=Primary seat\fR .sp .6 .in +4 Name of the seat\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSeat Entry/ID=StaticSeat\fR .sp .6 .in +4 Specifies the unique ID of the seat\&. If the value is NULL, then \fBconsole-kit-daemon\fR will provide a value\&. The ID may only contain the ASCII characters [A-Z][a=z][0-9]_"\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSeat Entry/Hidden=false\fR .sp .6 .in +4 If this value is set to "false", then ConsoleKit will create this seat\&. Otherwise, the seat will not be created\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSeat Entry/Devices\fR .sp .6 .in +4 This value is not currently supported\&. In the future, it is planned that ConsoleKit will provide the ability to manage how device permissions are managed, and this key is a placeholder\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSeat Entry/Sessions=Local\fR .sp .6 .in +4 List of sessions to start on the seat, separated by the ";" character\&. Each session must be defined in a ConsoleKit session configuration file named \fB/etc/ConsoleKit/sessions\&.d/\fIsessions\fR\&.session\fR where \fIsessions\fR is the value of this key\&. .sp .sp 1 .in -4 .SS "ConsoleKit Session Configuration" .PP ConsoleKit session configuration files are located in the /etc/ConsoleKit/sessions\&.d directory\&. Each session configuration file ends with the \fB\&.session\fR suffix\&. Additional seat configuration files may be added\&. These files are in standard INI format\&. .PP The settings below are in "group/key" format, so to specify the "Session Entry/Name" value, the file shoulld contain these lines: .PP .nf [Session Entry] [\&.\&.\&.] Name=Customized Session .fi .PP The following keys are supported for configuring ConsoleKit sessions: .sp .ne 2 .mk \fBSession Entry/Name\fR .sp .6 .in +4 Unique name of the session\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSession Entry/Type\fR .sp .6 .in +4 Type of the session .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSession Entry/Description\fR .sp .6 .in +4 Description of the session\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBSession Entry/DisplayTemplate\fR .sp .6 .in +4 This specifies the display type to be used with the session\&. This corresponds to the file \fB/etc/ConsoleKit/displays\&.d/\fIdisplay_template\fR\&.display\fR where \fIdisplay_template\fR is the value of this key\&. .sp .sp 1 .in -4 .sp .ne 2 .mk \fBLocal/\fIvariable\fR\fR .sp .6 .in +4 The ConsoleKit display configuration file associated with the "Entry/DisplayTemplate" key specifies the command to run to launch the display\&. This command is defined in the ConsoleKit display configuration file in the key "X11/Exec"\&. This command can include variables that begin with the "$" character, such as "$display"\&. The values to be used for these variables can be defined in this section\&. So if the session configuration file contains the value "Local/display=:0", this will cause the variable used when launching the command to be replaced with the value "0"\&. .sp .sp 1 .in -4 .SS "ConsoleKit System Restart and Stop" .PP \fBconsole-kit-daemon\fR provides D-Bus interfaces that will restart or stop the system\&. When \fBconsole-kit-daemon\fR receives a D-Bus request to restart the system, it will run the \fB/usr/lib/ConsoleKit/scripts/ck-system-restart\fR script if the user has privilege to do this operation\&. When \fBconsole-kit-daemon\fR receives a D-Bus request to stop the system, it will run the \fB/usr/lib/ConsoleKit/scripts/ck-system-stop\fR script if the user has privilege to do this operation\&. .SH "EXAMPLES" .PP \fBExample 1: To start the ConsoleKit daemon\fR .PP .PP .nf example% \fBconsole-kit-daemon\fR .fi .PP \fBExample 2: To configure ConsoleKit to start multiple sessions on a single seat\fR .PP To start two local displays: DISPLAY ":0" on vt7 and DISPLAY ":1" on "vt8", edit the \fB00-primary\&.seat\fR file as follows: .PP .nf [Seat Entry] Version=1\&.0 Name=Primary seat Description=start static displays :0 on vt7 and :1 on vt8 Hidden=false Devices= Sessions=Local;Local2; .fi .PP Then, in addition to the original \fB/etc/ConsoleKit/sessions\&.d/Local\&.session\fR file, add the following \fB/etc/ConsoleKit/sessions\&.d/Local2\&.session\fR file: .PP .nf [Session Entry] Name=Local Type=LoginWindow Description=Local Login Screen DisplayTemplate=Local [Local] display=:1 vt=/dev/vt/8 .fi .PP .SH "SEE ALSO" .PP More information can be found at: .PP \fBhttps://github\&.com/ConsoleKit2/ConsoleKit2\fR .PP \fBck-history\fR(1), \fBck-launch-session\fR(1), \fBck-list-sessions\fR(1), \fBsvcadm\fR(1m), \fBenviron\fR(5), \fBsmf\fR(5), \fBconsole\fR(4) .SH "NOTES" .PP Brian Cameron, Sun Microsystems Inc\&., 2009\&. Copyright (c) 2009 by Sun Microsystems, Inc\&. .PP Some of the documentation in this manpage is from the ConsoleKit documentation written by William Jon McCann\&. ...\" created by instant / solbook-to-man, Sat 24 Oct 2009, 14:10 ...\" LSARC 2009/432 ConsoleKit consolekit2-1.2.6/doc/dbus/000077500000000000000000000000001446640754400154745ustar00rootroot00000000000000consolekit2-1.2.6/doc/dbus/.gitignore000066400000000000000000000001401446640754400174570ustar00rootroot00000000000000Makefile Makefile.in ConsoleKit.xml org.freedesktop.ConsoleKit.*.ref.xml ConsoleKit.html *.o *~ consolekit2-1.2.6/doc/dbus/ConsoleKit.xml.in000066400000000000000000000041061446640754400206760ustar00rootroot00000000000000 ]> ConsoleKit2 @VERSION@ Documentation Version @VERSION@ William Jon McCann
william.jon.mccann@gmail.com
Eric Koegel
eric.koegel@gmail.com
Introduction Concepts &Intro; &Terms; &Design; Reference D-Bus API Reference ConsoleKit2 provides a D-Bus API for programs to obtain information about the users, sessions, and seats that are present on a system. Please see the other sections of this manual for an introduction to these concepts. This API is not yet stable and is likely to change in the future. &dbus-Manager; &dbus-Seat; &dbus-Session; Index
consolekit2-1.2.6/doc/dbus/Makefile.am000066400000000000000000000026201446640754400175300ustar00rootroot00000000000000NULL = SPEC_XML_FILES = \ ConsoleKit.xml \ ck-introduction.xml \ ck-terms.xml \ ck-design.xml \ org.freedesktop.ConsoleKit.Manager.ref.xml \ org.freedesktop.ConsoleKit.Seat.ref.xml \ org.freedesktop.ConsoleKit.Session.ref.xml \ $(NULL) if DOCBOOK_DOCS_ENABLED htmldocdir = $(docdir)/spec htmldoc_DATA = ConsoleKit.html ConsoleKit.html : $(SPEC_XML_FILES) $(XMLTO) $(XMLTO_FLAGS) xhtml-nochunks -m $(top_srcdir)/doc/dbus/config.xsl ConsoleKit.xml endif # DOCBOOK_DOCS_ENABLED org.freedesktop.ConsoleKit.Manager.ref.xml : $(top_srcdir)/src/org.freedesktop.ConsoleKit.Manager.xml spec-to-docbook.xsl $(XSLTPROC) $(top_srcdir)/doc/dbus/spec-to-docbook.xsl $< | tail -n +2 > $@ org.freedesktop.ConsoleKit.Seat.ref.xml : $(top_srcdir)/src/org.freedesktop.ConsoleKit.Seat.xml spec-to-docbook.xsl $(XSLTPROC) $(top_srcdir)/doc/dbus/spec-to-docbook.xsl $< | tail -n +2 > $@ org.freedesktop.ConsoleKit.Session.ref.xml : $(top_srcdir)/src/org.freedesktop.ConsoleKit.Session.xml spec-to-docbook.xsl $(XSLTPROC) $(top_srcdir)/doc/dbus/spec-to-docbook.xsl $< | tail -n +2 > $@ EXTRA_DIST = \ spec-to-docbook.xsl \ ConsoleKit.xml.in \ config.xsl \ docbook.css \ dbus-introspect-docs.dtd \ $(SPEC_XML_FILES) $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in \ $(NULL) clean-local: rm -f *~ *.ref.xml rm -f ConsoleKit.html check-local: xmllint --noout --noent --valid ConsoleKit.xml consolekit2-1.2.6/doc/dbus/ck-design.xml000066400000000000000000000161731446640754400200720ustar00rootroot00000000000000 Design Session Lifecycle The session leader process is responsible for asking ConsoleKit2 to open a new session. In this respect, it is similar to the traditional POSIX user login accounting framework. In the typical case, the session leader is either an immediate descendant of a login manager or the login manager itself. The leader makes a connection to the D-Bus system bus and asks ConsoleKit2 to open a session. There are two methods available for opening a session: org.freedesktop.ConsoleKit.Manager.OpenSession() and org.freedesktop.ConsoleKit.Manager.OpenSessionWithParameters(). If the operation succeeds, a secret cookie will be returned to the session leader. The session leader should store this secret in the environment as XDG_SESSION_COOKIE so that it may be shared with its child processes. At this point the session will be registered with ConsoleKit2 and a particular set of information about the session will be stored along with it. ConsoleKit2 will decide, based on the information associated with the session, what Seat the session will be added to. It will also be determined, based on the same set of information, whether the Session will control the hardware associated with the Seat. In other words, whether the Session will be active for the Seat it is attached to. The exact mechanism for this determination depends on the type of Seat and the capabilities of the host system. The Session will remain open until the Session Leader disconnects from the D-Bus system bus or calls org.freedesktop.ConsoleKit.Manager.CloseSession(). The session will be removed from its Seat, and deregistered. Expected Usage Use of this service will usually follow one of the following patterns: Text Login Manager This pattern operates as the Session Leader for a new Session. This pattern needs: To open a new Session. To set properties for the Session. To maintain a connection to the D-Bus system bus. To close the Session at logout. Graphical Login Manager In addition to the requirements for the Text Graphical Login Manager, this pattern is typically used to show information about currently open sessions. It needs: To determine which Seat it is running on. To know if the current seat supports session switching. A list of all sessions on the current Seat. To know which session is active for the current Seat. To know when the session active state changes. To know when sessions are added or removed. Access to the metadata for any open Session. System Daemon This is generally a daemon process running outside of a user session as a special user. This pattern needs: To know if any user sessions are open. To know if the system is currently being used. Hardware Abstraction Layer This is a special case of System Daemon that provides catalogs and control mechanisms for hardware devices. In addition to the requirements of System Daemon, this pattern needs: To determine what hardware is associated with a Seat. To determine what Session is active and inactive on a particular Seat. To know when the session active state changes. To determine what Session a process belongs to. Fast User Switching Agent This is related to the Graphical Login Manager and provides a shortcut to similar functionality. It is usually a tool available in the user session that allows one to quickly switch to another user session. This pattern needs: To determine which session it is running in. To determine which Seat it is running on. To know if the current seat supports session switching. A list of all sessions on the current Seat. Which session is active for the current Seat. To know when the session active state changes. Access to the metadata for any open Session. To know when sessions are added or removed. Session Daemon (aka Policy Agent) This is typically a daemon running in a user session that acts on policy only when the session is active. This pattern needs: To determine which session it is running in. To know when the session active state changes. Session Application This is typically an application running in a user session that may alter its behavior when the session active state changes. This pattern needs: To determine which session it is running in. To know when the session active state changes. consolekit2-1.2.6/doc/dbus/ck-introduction.xml000066400000000000000000000026551446640754400213420ustar00rootroot00000000000000 Introduction About ConsoleKit2 is a framework for keeping track of the various users, sessions, and seats present on a system. It provides a mechanism for software to react to changes of any of these items or of any of the metadata associated with them. ConsoleKit2 also allows fast switching between open sessions on the computer. ConsoleKit2 is a fork of ConsoleKit since it is no longer maintained. Information on ConsoleKit can be found at: http://freedesktop.org/wiki/Software/ConsoleKit/ William Jon McCann was the primary maintainer of ConsoleKit and most of this documentation was written by him for ConsoleKit. It has been adapted for ConsoleKit2. Defining the Problem A simple example is two users logging into a computer at the same time. They may be sharing the same set of hardware for their graphical session, such as the monitor, keyboard, and mouse. ConsoleKit2 will keep track of those resouces and which session is active and should have use of that hardware at a given time. Relevant art Logind is a Linux daemon providing the similar functionality to ConsoleKit2. consolekit2-1.2.6/doc/dbus/ck-terms.xml000066400000000000000000000044741446640754400177540ustar00rootroot00000000000000 Terminology Session A session is a collection of all processes that share knowledge of a secret. In the typical (or ideal) case, these processes all originate from a single common ancestor. As an implementation detail, for now, this secret should be stored in the process environment by the session leader under the name XDG_SESSION_COOKIE. When and if we are able to take advantage of a mechanism in the underlying system to store session registration information - we will. However, such a mechanism is not known at the present time. Using an environment variable does have certain advantages. For one, it is quite easy for a process to opt-out of a Session by simply unsetting the XDG_SESSION_COOKIE variable. Limitations of using an environment variable implementation include not being able to strictly limit visibility of the secret to a particular process ancestry. So, it is not possible to enforce session boundaries other than on a per-user basis. For example, we don't yet have a way to prevent a process from moving between sessions owned by the same user. Session leader The session leader is the process that requests that a new session be opened. It does this by connecting to the D-Bus system bus and using either org.freedesktop.ConsoleKit.Manager.OpenSession() or org.freedesktop.ConsoleKit.Manager.OpenSessionWithParameters(). The session that it registers will remain open until the connection to the system bus is lost or it calls org.freedesktop.ConsoleKit.Manager.CloseSession(). The session leader is the only process for which CloseSession() will be allowed. Seat A seat is a collection of sessions and a set of hardware (usually at least a keyboard and mouse). Only one session may be active on a seat at a time. At the present time, all Sessions that are considered "local" to a system will be added the the first Seat and every other Session will be added to its own Seat. True, hardware, multi-seat capabilities will be added in a later release. consolekit2-1.2.6/doc/dbus/config.xsl000066400000000000000000000004021446640754400174650ustar00rootroot00000000000000 consolekit2-1.2.6/doc/dbus/dbus-introspect-docs.dtd000066400000000000000000000021371446640754400222470ustar00rootroot00000000000000 consolekit2-1.2.6/doc/dbus/docbook.css000066400000000000000000000017111446640754400176260ustar00rootroot00000000000000body { font-family: sans-serif; } h1.title { } .permission { color: #ee0000; text-decoration: underline; } .synopsis, .classsynopsis { background: #eeeeee; border: solid 1px #aaaaaa; padding: 0.5em; } .programlisting { background: #eeeeff; border: solid 1px #aaaaff; padding: 0.5em; } .variablelist { padding: 4px; margin-left: 3em; } .variablelist td:first-child { vertical-align: top; } td.shortcuts { color: #770000; font-size: 80%; } div.refnamediv { margin-top: 2em; } div.toc { border: 2em; } a { text-decoration: none; } a:hover { text-decoration: underline; color: #FF0000; } div.table table { border-collapse: collapse; border-spacing: 0px; border-style: solid; border-color: #777777; border-width: 1px; } div.table table td, div.table table th { border-style: solid; border-color: #777777; border-width: 1px; padding: 3px; vertical-align: top; } div.table table th { background-color: #eeeeee; } consolekit2-1.2.6/doc/dbus/spec-to-docbook.xsl000066400000000000000000000472651446640754400212320ustar00rootroot00000000000000 interface Methods Signals Implemented Interfaces Objects implementing also implements org.freedesktop.DBus.Introspectable, org.freedesktop.DBus.Properties Properties Description Details Signal Details Property Details : <anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute></anchor>The "<xsl:value-of select="@name"/>" property '' : <anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute></anchor>The <xsl:value-of select="@name"/> signal () : Since /> is deprecated since version and should not be used in newly-written code. Use : :: . instead. See also: : Errors : Permissions <anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute></anchor><xsl:value-of select="@name"/> () () :'' ::() .() '' , '' , '' consolekit2-1.2.6/doc/libconsolekit/000077500000000000000000000000001446640754400174005ustar00rootroot00000000000000consolekit2-1.2.6/doc/libconsolekit/Makefile.am000066400000000000000000000056631446640754400214460ustar00rootroot00000000000000 # The name of the module, e.g. 'glib'. DOC_MODULE=libconsolekit # Uncomment for versioned docs and specify the version of the module, e.g. '2'. DOC_MODULE_VERSION=1.0 # The top-level XML file. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml # Directories containing the source code. # gtk-doc will search all .c and .h files beneath these paths # for inline comments documenting functions and macros. # e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk DOC_SOURCE_DIR=$(top_srcdir)/libconsolekit # Extra options to pass to gtkdoc-scangobj. Normally not needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS= # Extra options to supply to gtkdoc-mkdb # e.g. MKDB_OPTIONS=--xml-mode --output-format=xml MKDB_OPTIONS=--xml-mode --output-format=xml # Extra options to supply to gtkdoc-mkhtml MKHTML_OPTIONS= # Extra options to supply to gtkdoc-fixref. Normally not needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB=$(top_srcdir)/libconsolekit/*.h CFILE_GLOB=$(top_srcdir)/libconsolekit/*.c # Extra header to include when scanning, which are not under DOC_SOURCE_DIR # e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h EXTRA_HFILES= # Header files or dirs to ignore when scanning. Use base file/dir names # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code IGNORE_HFILES=test-libconsolekit.c # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.xml building.xml changes-2.0.xml content_files= # Files where gtk-doc abbrevations (#GtkWidget) are expanded # e.g. expand_content_files=running.xml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) GTKDOC_CFLAGS= \ -I$(top_srcdir) \ -I$(top_builddir) \ -I$(top_srcdir)/libconsolekit \ $(GLIB_CFLAGS) \ $(GIO_CFLAGS) \ $(GIO_UNIX_CFLAGS) \ $(NULL) GTKDOC_LIBS= \ $(top_builddir)/libconsolekit/libconsolekit.la \ $(GLIB_LIBS) \ $(GIO_LIBS) \ $(GIO_UNIX_LIBS) \ $(NULL) # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Comment this out if you want 'make check' to test you doc status # and run some sanity checks if ENABLE_GTK_DOC TESTS_ENVIRONMENT = \ DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) TESTS = $(GTKDOC_CHECK) endif -include $(top_srcdir)/git.mk consolekit2-1.2.6/doc/libconsolekit/libconsolekit-docs.xml000066400000000000000000000031331446640754400237110ustar00rootroot00000000000000 ]> ConsoleKit2 Reference Manual Version 1.0 2017 Eric Koegel Eric Koegel
eric.koegel@gmail.com
libconsolekit - Helper library to query various ConsoleKit properties API Index Version 1.0 API Index Version 1.2 API Index Deprecated API Symbols
consolekit2-1.2.6/doc/libconsolekit/libconsolekit-overrides.txt000066400000000000000000000000001446640754400247700ustar00rootroot00000000000000consolekit2-1.2.6/doc/libconsolekit/libconsolekit-sections.txt000066400000000000000000000014271446640754400246330ustar00rootroot00000000000000
libconsolekit LibConsoleKitError lib_consolekit_error_quark lib_consolekit_new lib_consolekit_seat_get_active lib_consolekit_seat_get_sessions lib_consolekit_seat_can_multi_session lib_consolekit_session_is_active lib_consolekit_session_is_remote lib_consolekit_session_get_class lib_consolekit_session_get_uid lib_consolekit_session_get_seat lib_consolekit_session_get_state lib_consolekit_session_get_display lib_consolekit_session_get_remote_host lib_consolekit_session_get_tty lib_consolekit_session_get_type lib_consolekit_session_get_vt lib_consolekit_pid_get_session LIB_CONSOLEKIT LIB_CONSOLEKIT_CLASS LIB_CONSOLEKIT_GET_CLASS LIB_IS_CONSOLEKIT LIB_IS_CONSOLEKIT_CLASS LIB_TYPE_CONSOLEKIT LibConsoleKit lib_consolekit_get_type
consolekit2-1.2.6/doc/libconsolekit/libconsolekit.types000066400000000000000000000000301446640754400233200ustar00rootroot00000000000000lib_consolekit_get_type consolekit2-1.2.6/libck-connector/000077500000000000000000000000001446640754400170465ustar00rootroot00000000000000consolekit2-1.2.6/libck-connector/.gitignore000066400000000000000000000001151446640754400210330ustar00rootroot00000000000000*.la *.lo *.o .deps .libs Makefile Makefile.in test-connector ck-connector.pcconsolekit2-1.2.6/libck-connector/Makefile.am000066400000000000000000000020401446640754400210760ustar00rootroot00000000000000NULL = AM_CFLAGS = \ -I. \ $(LIBDBUS_CFLAGS) \ $(NULL) lib_LTLIBRARIES = \ libck-connector.la \ $(NULL) libck_connectorincludedir = $(includedir)/ConsoleKit/ck-connector libck_connectorinclude_HEADERS = \ ck-connector.h \ $(NULL) libck_connector_la_SOURCES = \ ck-connector.c \ ck-connector.h \ $(NULL) if BUILD_TESTS noinst_PROGRAMS = \ test-connector \ $(NULL) test_connector_SOURCES = \ test-connector.c \ $(NULL) test_connector_LDADD = \ libck-connector.la \ $(LIBDBUS_LIBS) \ $(NULL) endif # BUILD_TESTS # soname management for libck-connector LIBCKCON_LT_CURRENT=0 LIBCKCON_LT_REVISION=0 LIBCKCON_LT_AGE=0 libck_connector_la_LIBADD = \ $(LIBDBUS_LIBS) \ $(NULL) libck_connector_la_LDFLAGS = \ -version-info $(LIBCKCON_LT_CURRENT):$(LIBCKCON_LT_REVISION):$(LIBCKCON_LT_AGE) \ $(NULL) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = ck-connector.pc EXTRA_DIST = \ ck-connector.pc.in \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in clean-local: rm -f *~ consolekit2-1.2.6/libck-connector/ck-connector.c000066400000000000000000000733301446640754400216050ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * ck-connector.c : Code for login managers to register with ConsoleKit. * * Copyright (c) 2007 David Zeuthen * Copyright (c) 2007 William Jon McCann * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include "ck-connector.h" #define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) #if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) #define _CK_FUNCTION_NAME __func__ #elif defined(__GNUC__) || defined(_MSC_VER) #define _CK_FUNCTION_NAME __FUNCTION__ #else #define _CK_FUNCTION_NAME "unknown function" #endif #define CK_CONNECTOR_ERROR "org.freedesktop.CkConnector.Error" #define _CK_WARNING_FORMAT "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n" #define _ck_return_if_fail(condition) do { \ if (!(condition)) { \ fprintf (stderr, _CK_WARNING_FORMAT, _CK_FUNCTION_NAME, #condition, __FILE__, __LINE__); \ return; \ } } while (0) #define _ck_return_val_if_fail(condition, val) do { \ if (!(condition)) { \ fprintf (stderr, _CK_WARNING_FORMAT, _CK_FUNCTION_NAME, #condition, __FILE__, __LINE__); \ return val; \ } } while (0) struct _CkConnector { int refcount; char *cookie; char *ssid; char *runtime_dir; dbus_bool_t session_created; DBusConnection *connection; }; static struct { char *name; int type; } parameter_lookup[] = { { "display-device", DBUS_TYPE_STRING }, { "x11-display-device", DBUS_TYPE_STRING }, { "x11-display", DBUS_TYPE_STRING }, { "remote-host-name", DBUS_TYPE_STRING }, { "session-type", DBUS_TYPE_STRING }, { "is-local", DBUS_TYPE_BOOLEAN }, { "unix-user", DBUS_TYPE_INT32 }, }; static int lookup_parameter_type (const char *name) { unsigned int i; int type; type = DBUS_TYPE_INVALID; for (i = 0; i < N_ELEMENTS (parameter_lookup); i++) { if (strcmp (name, parameter_lookup[i].name) == 0) { type = parameter_lookup[i].type; break; } } return type; } static dbus_bool_t add_param_basic (DBusMessageIter *iter_array, const char *name, int type, const void *value) { DBusMessageIter iter_struct; DBusMessageIter iter_variant; const char *container_type; switch (type) { case DBUS_TYPE_STRING: container_type = DBUS_TYPE_STRING_AS_STRING; break; case DBUS_TYPE_BOOLEAN: container_type = DBUS_TYPE_BOOLEAN_AS_STRING; break; case DBUS_TYPE_INT32: container_type = DBUS_TYPE_INT32_AS_STRING; break; default: goto oom; break; } if (! dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct)) { goto oom; } if (! dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name)) { goto oom; } if (! dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_VARIANT, container_type, &iter_variant)) { goto oom; } if (! dbus_message_iter_append_basic (&iter_variant, type, value)) { goto oom; } if (! dbus_message_iter_close_container (&iter_struct, &iter_variant)) { goto oom; } if (! dbus_message_iter_close_container (iter_array, &iter_struct)) { goto oom; } return TRUE; oom: return FALSE; } /* Frees all resources allocated and disconnects from the system * message bus. */ static void _ck_connector_free (CkConnector *connector) { if (connector->connection != NULL) { /* it's a private connection so it's all good */ dbus_connection_close (connector->connection); } if (connector->cookie != NULL) { free (connector->cookie); } if (connector->ssid != NULL) { free (connector->ssid); } if (connector->runtime_dir != NULL) { free (connector->runtime_dir); } free (connector); } /** * Decrements the reference count of a CkConnector, disconnecting * from the bus and freeing the connector if the count reaches 0. * * @param connector the connector * @see ck_connector_ref */ void ck_connector_unref (CkConnector *connector) { _ck_return_if_fail (connector != NULL); /* Probably should use some kind of atomic op here */ connector->refcount -= 1; if (connector->refcount == 0) { _ck_connector_free (connector); } } /** * Increments the reference count of a CkConnector. * * @param connector the connector * @returns the connector * @see ck_connector_unref */ CkConnector * ck_connector_ref (CkConnector *connector) { _ck_return_val_if_fail (connector != NULL, NULL); /* Probably should use some kind of atomic op here */ connector->refcount += 1; return connector; } /** * Constructs a new Connector to communicate with the ConsoleKit * daemon. Returns #NULL if memory can't be allocated for the * object. * * @returns a new CkConnector, free with ck_connector_unref() */ CkConnector * ck_connector_new (void) { CkConnector *connector; connector = calloc (1, sizeof (CkConnector)); if (connector == NULL) { goto oom; } connector->refcount = 1; connector->connection = NULL; connector->cookie = NULL; connector->session_created = FALSE; connector->ssid = NULL; connector->runtime_dir = NULL; oom: return connector; } /** * Connects to the D-Bus system bus daemon and issues the method call * OpenSession on the ConsoleKit manager interface. The * connection to the bus is private. * * Returns FALSE on OOM, if the system bus daemon is not running, if * the ConsoleKit daemon is not running or if the caller doesn't have * sufficient privileges. * * @returns #TRUE if the operation succeeds */ dbus_bool_t ck_connector_open_session (CkConnector *connector, DBusError *error) { DBusError local_error; DBusMessage *message; DBusMessage *reply; dbus_bool_t ret; char *cookie; _ck_return_val_if_fail (connector != NULL, FALSE); _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); reply = NULL; message = NULL; ret = FALSE; dbus_error_init (&local_error); connector->connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &local_error); if (connector->connection == NULL) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to open session: %s", local_error.message); dbus_error_free (&local_error); } goto out; } dbus_connection_set_exit_on_disconnect (connector->connection, FALSE); message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", "OpenSession"); if (message == NULL) { goto out; } dbus_error_init (&local_error); reply = dbus_connection_send_with_reply_and_block (connector->connection, message, -1, &local_error); if (reply == NULL) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to open session: %s", local_error.message); dbus_error_free (&local_error); goto out; } } dbus_error_init (&local_error); if (! dbus_message_get_args (reply, &local_error, DBUS_TYPE_STRING, &cookie, DBUS_TYPE_INVALID)) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to open session: %s", local_error.message); dbus_error_free (&local_error); goto out; } } connector->cookie = strdup (cookie); if (connector->cookie == NULL) { goto out; } connector->session_created = TRUE; ret = TRUE; out: if (reply != NULL) { dbus_message_unref (reply); } if (message != NULL) { dbus_message_unref (message); } return ret; } static dbus_bool_t ck_connector_open_session_with_parameters_valist (CkConnector *connector, DBusError *error, const char *first_parameter_name, va_list var_args) { DBusError local_error; DBusMessage *message; DBusMessage *reply; DBusMessageIter iter; DBusMessageIter iter_array; dbus_bool_t ret; char *cookie; const char *name; _ck_return_val_if_fail (connector != NULL, FALSE); reply = NULL; message = NULL; ret = FALSE; dbus_error_init (&local_error); connector->connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &local_error); if (connector->connection == NULL) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to open session: %s", local_error.message); dbus_error_free (&local_error); } goto out; } dbus_connection_set_exit_on_disconnect (connector->connection, FALSE); message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", "OpenSessionWithParameters"); if (message == NULL) { goto out; } dbus_message_iter_init_append (message, &iter); if (! dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(sv)", &iter_array)) { goto out; } name = first_parameter_name; while (name != NULL) { int type; const void *value; dbus_bool_t res; type = lookup_parameter_type (name); value = va_arg (var_args, const void *); if (type == DBUS_TYPE_INVALID) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unknown parameter: %s", name); goto out; } res = add_param_basic (&iter_array, name, type, value); if (! res) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Error adding parameter: %s", name); goto out; } name = va_arg (var_args, char *); } if (! dbus_message_iter_close_container (&iter, &iter_array)) { goto out; } dbus_error_init (&local_error); reply = dbus_connection_send_with_reply_and_block (connector->connection, message, -1, &local_error); if (reply == NULL) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to open session: %s", local_error.message); dbus_error_free (&local_error); goto out; } } dbus_error_init (&local_error); if (! dbus_message_get_args (reply, &local_error, DBUS_TYPE_STRING, &cookie, DBUS_TYPE_INVALID)) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to open session: %s", local_error.message); dbus_error_free (&local_error); goto out; } } connector->cookie = strdup (cookie); if (connector->cookie == NULL) { goto out; } connector->session_created = TRUE; ret = TRUE; out: if (reply != NULL) { dbus_message_unref (reply); } if (message != NULL) { dbus_message_unref (message); } return ret; } /** * Opens a new session with parameter from variable argument list. The * variable argument list should contain the name of each parameter * followed by the value to append. * For example: * * @code * * DBusError error; * dbus_int32_t v_INT32 = 500; * const char *v_STRING = "/dev/tty3"; * * dbus_error_init (&error); * ck_connector_open_session_with_parameters (connector, * &error, * "unix-user", &v_INT32, * "display-device", &v_STRING, * NULL); * @endcode * * @param error error output * @param first_parameter_name name of the first parameter * @param ... value of first parameter, list of additional name-value pairs * @returns #TRUE on success */ dbus_bool_t ck_connector_open_session_with_parameters (CkConnector *connector, DBusError *error, const char *first_parameter_name, ...) { va_list var_args; dbus_bool_t ret; _ck_return_val_if_fail (connector != NULL, FALSE); _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); va_start (var_args, first_parameter_name); ret = ck_connector_open_session_with_parameters_valist (connector, error, first_parameter_name, var_args); va_end (var_args); return ret; } /** * Connects to the D-Bus system bus daemon and issues the method call * OpenSessionWithParameters on the ConsoleKit manager interface. The * connection to the bus is private. * * The only parameter that is optional is x11_display - it may be set * to NULL if there is no X11 server associated with the session. * * Returns FALSE on OOM, if the system bus daemon is not running, if * the ConsoleKit daemon is not running or if the caller doesn't have * sufficient privileges. * * @param user UID for the user owning the session * @param display_device the tty device for the session * @param x11_display the value of the X11 DISPLAY for the session * @returns #TRUE if the operation succeeds */ dbus_bool_t ck_connector_open_session_for_user (CkConnector *connector, uid_t user, const char *display_device, const char *x11_display, DBusError *error) { dbus_bool_t ret; _ck_return_val_if_fail (connector != NULL, FALSE); _ck_return_val_if_fail (display_device != NULL, FALSE); _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); ret = ck_connector_open_session_with_parameters (connector, error, "display-device", &display_device, "x11-display", &x11_display, "unix-user", &user, NULL); return ret; } /** * Gets the cookie for the current open session. * Returns #NULL if no session is open. * * @returns a constant string with the cookie. */ const char * ck_connector_get_cookie (CkConnector *connector) { _ck_return_val_if_fail (connector != NULL, NULL); if (! connector->session_created) { return NULL; } else { return connector->cookie; } } static dbus_bool_t ck_connector_get_ssid (CkConnector *connector, DBusError *error) { DBusError local_error; DBusMessage *message; DBusMessage *reply; char *ssid; dbus_bool_t ret; _ck_return_val_if_fail (connector != NULL, FALSE); reply = NULL; message = NULL; ssid = NULL; ret = FALSE; if (!connector->session_created || connector->cookie == NULL) { return ret; } dbus_error_init (&local_error); message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", "GetSessionForCookie"); if (message == NULL) { goto out; } if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &(connector->cookie), DBUS_TYPE_INVALID)) { goto out; } dbus_error_init (&local_error); reply = dbus_connection_send_with_reply_and_block (connector->connection, message, -1, &local_error); if (reply == NULL) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to get session for cookie: %s, no reply from dbus", local_error.message); dbus_error_free (&local_error); goto out; } } if (!dbus_message_get_args (reply, error, DBUS_TYPE_OBJECT_PATH, &ssid, DBUS_TYPE_INVALID)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to get session for cookie: %s", local_error.message); dbus_error_free (&local_error); goto out; } connector->ssid = strdup (ssid); if (connector->ssid == NULL) { goto out; } ret = TRUE; out: if (reply != NULL) { dbus_message_unref (reply); } if (message != NULL) { dbus_message_unref (message); } return ret; } /** * Gets the XDG_RUNTIME_DIR for the current open session. * Returns #NULL if no session is open. * * @returns a constant string with the XDG_RUNTIME_DIR. */ const char * ck_connector_get_runtime_dir (CkConnector *connector, DBusError *error) { DBusError local_error; DBusMessage *message; char *runtime_dir; DBusMessage *reply; _ck_return_val_if_fail (connector != NULL, NULL); if (!connector->session_created || connector->cookie == NULL) { return NULL; } /* If we already have the runtime dir, supply it again */ if (connector->runtime_dir != NULL) { return connector->runtime_dir; } /* get the ssid if we don't already have it */ if (connector->ssid == NULL) { if (ck_connector_get_ssid (connector, error) == FALSE) { return NULL; } } reply = NULL; message = NULL; runtime_dir = NULL; if (!connector->session_created || connector->cookie == NULL) { return NULL; } dbus_error_init (&local_error); message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", connector->ssid, "org.freedesktop.ConsoleKit.Session", "GetXDGRuntimeDir"); if (message == NULL) { goto out; } dbus_error_init (&local_error); reply = dbus_connection_send_with_reply_and_block (connector->connection, message, -1, &local_error); if (reply == NULL) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to get runtime dir for session: %s", local_error.message); dbus_error_free (&local_error); goto out; } } if (!dbus_message_get_args (reply, error, DBUS_TYPE_STRING, &runtime_dir, DBUS_TYPE_INVALID)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to get runtime dir for session: %s", local_error.message); dbus_error_free (&local_error); goto out; } connector->runtime_dir = strdup (runtime_dir); if (connector->runtime_dir == NULL) { goto out; } out: if (reply != NULL) { dbus_message_unref (reply); } if (message != NULL) { dbus_message_unref (message); } return connector->runtime_dir; } /** * Issues the CloseSession method call on the ConsoleKit manager * interface. * * Returns FALSE on OOM, if the system bus daemon is not running, if * the ConsoleKit daemon is not running, if the caller doesn't have * sufficient privilege or if a session isn't open. * * @returns #TRUE if the operation succeeds */ dbus_bool_t ck_connector_close_session (CkConnector *connector, DBusError *error) { DBusError local_error; DBusMessage *message; DBusMessage *reply; dbus_bool_t ret; dbus_bool_t session_closed; _ck_return_val_if_fail (connector != NULL, FALSE); _ck_return_val_if_fail ((error) == NULL || !dbus_error_is_set ((error)), FALSE); reply = NULL; message = NULL; ret = FALSE; if (!connector->session_created || connector->cookie == NULL) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to close session: %s", "no session open"); goto out; } dbus_error_init (&local_error); message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", "CloseSession"); if (message == NULL) { goto out; } if (! dbus_message_append_args (message, DBUS_TYPE_STRING, &(connector->cookie), DBUS_TYPE_INVALID)) { goto out; } dbus_error_init (&local_error); reply = dbus_connection_send_with_reply_and_block (connector->connection, message, -1, &local_error); if (reply == NULL) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to close session: %s", local_error.message); dbus_error_free (&local_error); goto out; } } dbus_error_init (&local_error); if (! dbus_message_get_args (reply, &local_error, DBUS_TYPE_BOOLEAN, &session_closed, DBUS_TYPE_INVALID)) { if (dbus_error_is_set (&local_error)) { dbus_set_error (error, CK_CONNECTOR_ERROR, "Unable to close session: %s", local_error.message); dbus_error_free (&local_error); goto out; } } if (! session_closed) { goto out; } connector->session_created = FALSE; ret = TRUE; out: if (reply != NULL) { dbus_message_unref (reply); } if (message != NULL) { dbus_message_unref (message); } return ret; } consolekit2-1.2.6/libck-connector/ck-connector.h000066400000000000000000000057211446640754400216110ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * ck-connector.h : Code for login managers to register with ConsoleKit. * * Copyright (c) 2007 David Zeuthen * Copyright (c) 2007 William Jon McCann * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef CK_CONNECTOR_H #define CK_CONNECTOR_H #include #include DBUS_BEGIN_DECLS struct _CkConnector; typedef struct _CkConnector CkConnector; CkConnector *ck_connector_new (void); CkConnector *ck_connector_ref (CkConnector *ckc); void ck_connector_unref (CkConnector *ckc); dbus_bool_t ck_connector_open_session_for_user (CkConnector *ckc, uid_t user, const char *tty, const char *x11_display, DBusError *error); dbus_bool_t ck_connector_open_session_with_parameters (CkConnector *ckc, DBusError *error, const char *first_parameter_name, ...); dbus_bool_t ck_connector_open_session (CkConnector *ckc, DBusError *error); const char *ck_connector_get_cookie (CkConnector *ckc); const char *ck_connector_get_runtime_dir (CkConnector *ckc, DBusError *error); dbus_bool_t ck_connector_close_session (CkConnector *ckc, DBusError *error); DBUS_END_DECLS #endif /* CK_CONNECTOR_H */ consolekit2-1.2.6/libck-connector/ck-connector.pc.in000066400000000000000000000004611446640754400223650ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@prefix@ libdir=@libdir@ includedir=@prefix@/include libexecdir=@libexecdir@ Name: ck-connector Description: Library for connecting new sessions to ConsoleKit Version: @VERSION@ Requires: dbus-1 Libs: -L${libdir} -lck-connector Cflags: -I${includedir}/ConsoleKit/ck-connector consolekit2-1.2.6/libck-connector/test-connector.c000066400000000000000000000103641446640754400221650ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2007 David Zeuthen * Copyright (c) 2007 William Jon McCann * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include "ck-connector.h" int main (int argc, char *argv[]) { CkConnector *connector; int ret; int res; DBusError error; int user; const char *display_device; const char *x11_display; const char *remote_host_name; ret = 1; connector = ck_connector_new (); if (connector == NULL) { printf ("OOM creating CkConnector\n"); goto out; } user = 730; display_device = "/dev/tty3"; x11_display = ":20"; remote_host_name = ""; dbus_error_init (&error); res = ck_connector_open_session_with_parameters (connector, &error, "unix-user", &user, "display-device", &display_device, "x11-display", &x11_display, "remote-host-name", &remote_host_name, NULL); if (! res) { if (dbus_error_is_set (&error)) { printf ("%s\n", error.message); dbus_error_free (&error); } else { printf ("cannot open CK session: OOM, D-Bus system bus not available,\n" "ConsoleKit not available or insufficient privileges.\n"); } goto out; } printf ("Session cookie is '%s'\n", ck_connector_get_cookie (connector)); if (ck_connector_get_runtime_dir (connector, &error) == NULL) { if (dbus_error_is_set (&error)) { printf ("Failed to get XDG_RUNTIME_DIR error is '%s'\n", error.message); dbus_error_free (&error); } else { printf ("Cannot get XDG_RUNTIME_DIR, out of memory error\n"); } } else { printf ("XDG_RUNTIME_DIR is '%s'\n", ck_connector_get_runtime_dir (connector, &error)); } sleep (20); dbus_error_init (&error); if (! ck_connector_close_session (connector, &error)) { if (dbus_error_is_set (&error)) { printf ("%s\n", error.message); dbus_error_free (&error); } else { printf ("Cannot close CK session: OOM, D-Bus system bus not available,\n" "ConsoleKit not available or insufficient privileges.\n"); } goto out; } ret = 0; out: if (connector != NULL) { ck_connector_unref (connector); } return ret; } consolekit2-1.2.6/libconsolekit/000077500000000000000000000000001446640754400166335ustar00rootroot00000000000000consolekit2-1.2.6/libconsolekit/Makefile.am000066400000000000000000000043421446640754400206720ustar00rootroot00000000000000NULL = CLEANFILES = AM_CFLAGS = \ -I. \ $(GLIB_CFLAGS) \ $(GIO_CFLAGS) \ $(GIO_UNIX_CFLAGS) \ $(NULL) lib_LTLIBRARIES = \ libconsolekit.la \ $(NULL) libconsolekitincludedir = $(includedir)/ConsoleKit/ libconsolekitinclude_HEADERS = \ libconsolekit.h \ sd-login.h \ $(NULL) libconsolekit_la_SOURCES = \ libconsolekit.c \ libconsolekit.h \ sd-compat.c \ sd-login.h \ $(NULL) # soname management for liblibconsolekit LIBCONSOLEKIT_LT_CURRENT=1 LIBCONSOLEKIT_LT_REVISION=0 LIBCONSOLEKIT_LT_AGE=0 libconsolekit_la_LIBADD = \ $(GLIB_LIBS) \ $(GIO_LIBS) \ $(GIO_UNIX_LIBS) \ $(NULL) libconsolekit_la_LDFLAGS = \ -version-info $(LIBCONSOLEKIT_LT_CURRENT):$(LIBCONSOLEKIT_LT_REVISION):$(LIBCONSOLEKIT_LT_AGE) \ $(NULL) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libconsolekit.pc CLEANFILES += libconsolekit.pc if BUILD_TESTS noinst_PROGRAMS = \ test-libconsolekit \ $(NULL) test_libconsolekit_SOURCES = \ libconsolekit.h \ test-libconsolekit.c \ $(NULL) test_libconsolekit_LDADD = \ $(GLIB_LIBS) \ $(GIO_LIBS) \ $(GIO_UNIX_LIBS) \ libconsolekit.la \ $(NULL) endif #build tests EXTRA_DIST = \ libconsolekit.pc.in \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = INTROSPECTION_SCANNER_ENV = CC="$(CC)" INTROSPECTION_SCANNER_ARGS = \ --add-include-path=$(srcdir) \ --warn-all \ --identifier-prefix=Lib \ --symbol-prefix=lib_ \ --symbol-prefix=sd_ INTROSPECTION_COMPILER_ARGS = \ --includedir=$(srcdir) \ --includedir=. if HAVE_INTROSPECTION introspection_sources = $(libconsolekit_la_SOURCES) libconsolekit-1.0.gir: libconsolekit.la Makefile libconsolekit_1_0_gir_INCLUDES = GObject-2.0 GLib-2.0 Gio-2.0 libconsolekit_1_0_gir_CFLAGS = $(AM_CFLAGS) libconsolekit_1_0_gir_LIBS = libconsolekit.la libconsolekit_1_0_gir_FILES = $(introspection_sources) libconsolekit_1_0_gir_EXPORT_PACKAGES = libconsolekit-1.0 INTROSPECTION_GIRS += libconsolekit-1.0.gir girdir = $(datadir)/gir-1.0 gir_DATA = $(INTROSPECTION_GIRS) typelibdir = $(libdir)/girepository-1.0 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) CLEANFILES += $(gir_DATA) $(typelib_DATA) endif clean-local: rm -f *~ consolekit2-1.2.6/libconsolekit/libconsolekit.c000066400000000000000000001606451446640754400216540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2017, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include "libconsolekit.h" #define CK_NAME "org.freedesktop.ConsoleKit" #define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" #define CK_MANAGER_NAME CK_NAME ".Manager" #define CK_SEAT_NAME CK_NAME ".Seat" #define CK_SESSION_NAME CK_NAME ".Session" #define CONSOLEKIT_ERROR lib_consolekit_error_quark () /** * SECTION:libconsolekit * @short_description: Helper library to query various ConsoleKit properties * @include: libconsolekit.h * * A #LibConsoleKit provides a way to easily query information from the ConsoleKit * daemon. */ static void lib_consolekit_finalize (GObject *object); /** * LibConsoleKit: * * The LibConsoleKit struct contains only private data. * It should only be accessed through the functions described below. */ struct _LibConsoleKit { GObject parent_instance; }; G_DEFINE_TYPE (LibConsoleKit, lib_consolekit, G_TYPE_OBJECT) /** * lib_consolekit_error_quark: * * Registers an error quark for #LibConsoleKit if necessary. * * Returns: the error quark used for #LibConsoleKit errors. **/ GQuark lib_consolekit_error_quark (void) { static GQuark error_quark = 0; if (error_quark == 0) error_quark = g_quark_from_static_string ("libck2-error-quark"); return error_quark; } static void lib_consolekit_class_init (LibConsoleKitClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = lib_consolekit_finalize; } static void lib_consolekit_init (LibConsoleKit *ck) { } static void lib_consolekit_finalize (GObject *object) { G_OBJECT_CLASS (lib_consolekit_parent_class)->finalize (object); } /** * lib_consolekit_new: (skip) * * Creates and returns a new instance of #LibConsoleKit. * * Return value: (transfer full): a new instance of #LibConsoleKit. * * Since: 1.0 **/ LibConsoleKit* lib_consolekit_new (void) { GObject *object; object = g_object_new (LIB_TYPE_CONSOLEKIT, NULL); return LIB_CONSOLEKIT (object); } /** * lib_consolekit_seat_get_active: * @ck : A #LibConsoleKit * @seat : The seat to query * @session : (out) (transfer full): The active session, if any * @uid : (out) (allow-none): The unix user the session belongs to * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the session and uid of the user who has the active session on * the seat, if any session is active. Free the session with g_free when * done. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_seat_get_active (LibConsoleKit *ck, const gchar *seat, gchar **session, uid_t *uid, GError **error) { GDBusProxy *seat_proxy = NULL; GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (seat == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Seat must not be NULL"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } /* connect to the ConsoleKit seat */ seat_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, seat, CK_SEAT_NAME, NULL, error); /* failed to connect */ if (seat_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (seat_proxy, "GetActiveSession", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the seat proxy */ g_clear_object(&seat_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "o", session); g_variant_unref (variant); variant = NULL; /* Don't care about uid? We're done */ if (uid == NULL) { return TRUE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, *session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetUnixUser", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "u", uid); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_uid_get_sessions: **/ gint lib_consolekit_uid_get_sessions (LibConsoleKit *ck, uid_t uid, gchar ***sessions, GError **error) { GDBusProxy *manager_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return -1; } /* connect to the ConsoleKit manager */ manager_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, CK_MANAGER_PATH, CK_MANAGER_NAME, NULL, error); /* failed to connect */ if (manager_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (manager_proxy, "GetSessionsForUnixUser", g_variant_new ("(u)", uid), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the seat proxy */ g_clear_object(&manager_proxy); if (variant == NULL) { return -1; } g_variant_get (variant, "(^ao)", sessions); g_variant_unref (variant); variant = NULL; return g_strv_length (*sessions); } /** * lib_consolekit_get_sessions: **/ gint lib_consolekit_get_sessions (LibConsoleKit *ck, gchar ***sessions, GError **error) { GDBusProxy *manager_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return -1; } /* connect to the ConsoleKit manager */ manager_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, CK_MANAGER_PATH, CK_MANAGER_NAME, NULL, error); /* failed to connect */ if (manager_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (manager_proxy, "GetSessions", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the seat proxy */ g_clear_object(&manager_proxy); if (variant == NULL) { return -1; } g_variant_get (variant, "(^ao)", sessions); g_variant_unref (variant); variant = NULL; return g_strv_length (*sessions); } /** * lib_consolekit_seat_get_sessions: * @ck : A #LibConsoleKit * @seat : The seat to query * @sessions: (out) (transfer full) (array zero-terminated=1): The sessions on the seat, if any * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the sessions on the seat. Free the sessions with g_strfreev when done. * * Return value: The number of sessions returned or -1 on failure * * Since: 1.0 **/ gint lib_consolekit_seat_get_sessions (LibConsoleKit *ck, const gchar *seat, gchar ***sessions, GError **error) { GDBusProxy *seat_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return -1; } if (seat == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Seat must not be NULL"); return -1; } if (sessions == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Sessions must not be NULL"); return -1; } /* connect to the ConsoleKit seat */ seat_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, seat, CK_SEAT_NAME, NULL, error); /* failed to connect */ if (seat_proxy == NULL) { return -1; } variant = g_dbus_proxy_call_sync (seat_proxy, "GetSessions", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the seat proxy */ g_clear_object(&seat_proxy); if (variant == NULL) { return -1; } g_variant_get (variant, "(^ao)", sessions); g_variant_unref (variant); variant = NULL; return g_strv_length (*sessions); } /** * lib_consolekit_seat_can_multi_session: * @ck : A #LibConsoleKit * @seat : The seat to query * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns whether the provided seat is capable of holding multiple sessions * at any given time. * * Return value: TRUE if capable of multiple sessions. * * Since: 1.0 **/ gboolean lib_consolekit_seat_can_multi_session (LibConsoleKit *ck, const gchar *seat, GError **error) { GDBusProxy *seat_proxy = NULL; GVariant *variant = NULL; gboolean can_activate = FALSE; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (seat == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Seat must not be NULL"); return FALSE; } /* connect to the ConsoleKit seat */ seat_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, seat, CK_SEAT_NAME, NULL, error); /* failed to connect */ if (seat_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (seat_proxy, "CanActivateSessions", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the seat proxy */ g_clear_object(&seat_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "b", &can_activate); g_variant_unref (variant); variant = NULL; return can_activate; } /** * lib_consolekit_session_is_active: * @ck : A #LibConsoleKit * @session : The session to query * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns whether the provided session is active. * * Return value: TRUE if the session is active. * * Since: 1.0 **/ gboolean lib_consolekit_session_is_active (LibConsoleKit *ck, const gchar *session, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; gboolean is_active = FALSE; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "IsActive", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "b", &is_active); g_variant_unref (variant); variant = NULL; return is_active; } /** * lib_consolekit_session_is_remote: * @ck : A #LibConsoleKit * @session : The session to query * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns whether the provided session is remote. * * Return value: TRUE if the session is remote, FALSE if local. Defaults to TRUE on error. * * Since: 1.0 **/ gboolean lib_consolekit_session_is_remote (LibConsoleKit *ck, const gchar *session, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; gboolean is_local = FALSE; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return TRUE; } variant = g_dbus_proxy_call_sync (session_proxy, "IsLocal", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return TRUE; } g_variant_get_child (variant, 0, "b", &is_local); g_variant_unref (variant); variant = NULL; /* We flip this because we want to know if we're remote */ return !is_local; } /** * lib_consolekit_session_get_uid: * @ck : A #LibConsoleKit * @session : The session to query * @uid : (out) (transfer full): unix-user who owns the session * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the unix user who owns the session. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_uid (LibConsoleKit *ck, const gchar *session, uid_t *uid, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (uid == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "uid must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetUnixUser", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "u", uid); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_seat: * @ck : A #LibConsoleKit * @session : The session to query * @seat : (out) (transfer full): The seat the session belongs to * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the seat the session belongs to. Free the seat string * with g_free when finished. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_seat (LibConsoleKit *ck, const gchar *session, gchar **seat, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (seat == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Seat must not be NULL"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetSeatId", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "o", seat); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_service: * @ck : A #LibConsoleKit * @session : The session to query * @service : (out) (transfer full): The session's service * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the service of the provided session. Defaults to: * "unspecified" - Unknown session service. * * Return value: TRUE on Success. * * Since: 1.2.4 **/ gboolean lib_consolekit_session_get_service (LibConsoleKit *ck, const gchar *session, gchar **service, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (service == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "service must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetSessionService", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "s", service); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_type: * @ck : A #LibConsoleKit * @session : The session to query * @type : (out) (transfer full): The session's display type * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the display type of the provided session. The following types * may be returned: * "x11" - An X11/Xorg based session * "wayland" - A Wayland based session * "tty" - A text console based session * "mir" - A session using the Mir display server * "unspecified" - Unknown session type. * * Note: Additional types may be added in the future. Free the type * string with g_free. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_type (LibConsoleKit *ck, const gchar *session, gchar **type, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (type == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "type must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetSessionType", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "s", type); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_class: * @ck : A #LibConsoleKit * @session : The session to query * @session_class : (out) (transfer full): The session's class * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the class of the provided session. The following classes * may be returned: * "user" - A normal user session, the default * "greeter" - Display Manager pseudo session * "lock-screen" - Screensaver based session * "background" - A long running background process that requires its own session * * Note: Additional classes may be added in the future. Free the session_class * string with g_free. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_class (LibConsoleKit *ck, const gchar *session, gchar **session_class, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (session_class == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "session_class must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetSessionClass", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "s", session_class); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_state: * @ck : A #LibConsoleKit * @session : The session to query * @state : (out) (transfer full): The session's state * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the current state of the provided session. The following states * may be returned: * "online" - Session is logged in but not active * "active" - Session is logged in and active * "closing" - Session is in the process of shutting down * * Note: Additional states may be added in the future. Free the state * string with g_free. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_state (LibConsoleKit *ck, const gchar *session, gchar **state, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (state == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "state must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetSessionState", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "s", state); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_display: * @ck : A #LibConsoleKit * @session : The session to query * @display : (out) (transfer full): The X11 display the session owns * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the display the session has, if any. Free the display string * with g_free when finished. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_display (LibConsoleKit *ck, const gchar *session, gchar **display, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (display == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Display must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetX11Display", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "s", display); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_remote_host: * @ck : A #LibConsoleKit * @session : The session to query * @remote_host : (out) (transfer full): The remote hostname, if any * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the hostname of the remote session the session has, if any. * Free the remote_host string with g_free when finished. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_remote_host (LibConsoleKit *ck, const gchar *session, gchar **remote_host, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (remote_host == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "remote_host must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetRemoteHostName", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "s", remote_host); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_session_get_tty: * @ck : A #LibConsoleKit * @session : The session to query * @tty : (out) (transfer full): The tty attached to the session * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the tty the session has, if any. * Free the tty string with g_free when finished. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_tty (LibConsoleKit *ck, const gchar *session, gchar **tty, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (tty == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "tty must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetX11DisplayDevice", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); if (variant == NULL) { g_clear_object(&session_proxy); return FALSE; } g_variant_get_child (variant, 0, "s", tty); g_variant_unref (variant); variant = NULL; /* We're not running X11, try for just the display device */ if (strlen (*tty) == 0) { g_free (*tty); variant = g_dbus_proxy_call_sync (session_proxy, "GetDisplayDevice", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); if (variant == NULL) { g_clear_object(&session_proxy); return FALSE; } g_variant_get_child (variant, 0, "s", tty); g_variant_unref (variant); variant = NULL; } /* We're done with the session proxy */ g_clear_object(&session_proxy); return TRUE; } /** * lib_consolekit_session_get_vt: * @ck : A #LibConsoleKit * @session : The session to query * @vt : (out) : The VT of the session, if any * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the VT the session is on, if any. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_session_get_vt (LibConsoleKit *ck, const gchar *session, guint *vt, GError **error) { GDBusProxy *session_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } if (vt == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "vt must not be NULL"); return FALSE; } /* connect to the ConsoleKit session */ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, session, CK_SESSION_NAME, NULL, error); /* failed to connect */ if (session_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (session_proxy, "GetVTNr", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the session proxy */ g_clear_object(&session_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "u", vt); g_variant_unref (variant); variant = NULL; return TRUE; } /** * lib_consolekit_pid_get_session: * @ck : A #LibConsoleKit * @pid : process to query * @session : (out) (transfer full): The session the pid belongs to * @error : (out) (allow-none) (transfer full): The error message if something failed * * Returns the session the pid belongs to, if any. * Free the session string with g_free when finished. * * Return value: TRUE on Success. * * Since: 1.0 **/ gboolean lib_consolekit_pid_get_session (LibConsoleKit *ck, pid_t pid, gchar **session, GError **error) { GDBusProxy *manager_proxy = NULL; GVariant *variant = NULL; if (ck == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Invalid LibConsoleKit"); return FALSE; } if (session == NULL) { g_set_error (error, CONSOLEKIT_ERROR, CONSOLEKIT_ERROR_INVALID_INPUT, "Session must not be NULL"); return FALSE; } /* connect to the ConsoleKit manager */ manager_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, CK_NAME, CK_MANAGER_PATH, CK_MANAGER_NAME, NULL, error); /* failed to connect */ if (manager_proxy == NULL) { return FALSE; } variant = g_dbus_proxy_call_sync (manager_proxy, "GetSessionByPID", g_variant_new ("(u)", pid), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); /* We're done with the manager proxy */ g_clear_object(&manager_proxy); if (variant == NULL) { return FALSE; } g_variant_get_child (variant, 0, "o", session); g_variant_unref (variant); variant = NULL; return TRUE; } consolekit2-1.2.6/libconsolekit/libconsolekit.h000066400000000000000000000175651446640754400216630ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2017, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIB_CONSOLEKIT_H_ #define LIB_CONSOLEKIT_H_ #include #define LIB_TYPE_CONSOLEKIT (lib_consolekit_get_type ()) #define LIB_CONSOLEKIT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), LIB_TYPE_CONSOLEKIT, LibConsoleKit)) #define LIB_CONSOLEKIT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), LIB_TYPE_CONSOLEKIT, LibConsoleKitClass)) #define LIB_IS_CONSOLEKIT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), LIB_TYPE_CONSOLEKIT)) #define LIB_IS_CONSOLEKIT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), LIB_TYPE_CONSOLEKIT)) #define LIB_CONSOLEKIT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), LIB_TYPE_CONSOLEKIT, LibConsoleKitClass)) typedef struct _LibConsoleKit LibConsoleKit; typedef struct { GObjectClass parent_class; } LibConsoleKitClass; /** * LibConsoleKitError: * @CONSOLEKIT_ERROR_FAILED: unknown or unclassified error * @CONSOLEKIT_ERROR_INVALID_INPUT: the variable passed into the calling function is invalid. * * Describes errors that may result from operations involving a #LibConsoleKit. * **/ typedef enum { CONSOLEKIT_ERROR_FAILED, CONSOLEKIT_ERROR_INVALID_INPUT } LibConsoleKitError; GQuark lib_consolekit_error_quark (void); GType lib_consolekit_get_type (void); LibConsoleKit *lib_consolekit_new (void); gboolean lib_consolekit_seat_get_active (LibConsoleKit *ck, const gchar *seat, gchar **session, uid_t *uid, GError **error); gint lib_consolekit_seat_get_sessions (LibConsoleKit *ck, const gchar *seat, gchar ***sessions, GError **error); gboolean lib_consolekit_seat_can_multi_session (LibConsoleKit *ck, const gchar *seat, GError **error); gboolean lib_consolekit_session_is_active (LibConsoleKit *ck, const gchar *session, GError **error); gboolean lib_consolekit_session_is_remote (LibConsoleKit *ck, const gchar *session, GError **error); gboolean lib_consolekit_session_get_uid (LibConsoleKit *ck, const gchar *session, uid_t *uid, GError **error); gboolean lib_consolekit_session_get_seat (LibConsoleKit *ck, const gchar *session, gchar **seat, GError **error); gboolean lib_consolekit_session_get_type (LibConsoleKit *ck, const gchar *session, gchar **type, GError **error); gboolean lib_consolekit_session_get_class (LibConsoleKit *ck, const gchar *session, gchar **session_class, GError **error); gboolean lib_consolekit_session_get_state (LibConsoleKit *ck, const gchar *session, gchar **state, GError **error); gboolean lib_consolekit_session_get_display (LibConsoleKit *ck, const gchar *session, gchar **display, GError **error); gboolean lib_consolekit_session_get_remote_host (LibConsoleKit *ck, const gchar *session, gchar **remote_host, GError **error); gboolean lib_consolekit_session_get_service (LibConsoleKit *ck, const gchar *session, gchar **service, GError **error); gboolean lib_consolekit_session_get_tty (LibConsoleKit *ck, const gchar *session, gchar **tty, GError **error); gboolean lib_consolekit_session_get_vt (LibConsoleKit *ck, const gchar *session, guint *vt, GError **error); gboolean lib_consolekit_pid_get_session (LibConsoleKit *ck, pid_t pid, gchar **session, GError **error); gint lib_consolekit_pid_get_sessions (LibConsoleKit *ck, pid_t pid, gchar **sessions, GError **error); gint lib_consolekit_uid_get_sessions (LibConsoleKit *ck, uid_t uid, gchar ***sessions, GError **error); gint lib_consolekit_get_sessions (LibConsoleKit *ck, gchar ***sessions, GError **error); #endif /* LIB_CONSOLEKIT_H_ */ consolekit2-1.2.6/libconsolekit/libconsolekit.pc.in000066400000000000000000000004761446640754400224340ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@prefix@ libdir=@libdir@ includedir=@prefix@/include libexecdir=@libexecdir@ Name: libconsolekit Description: Helper library to query various ConsoleKit properties Version: @VERSION@ Requires: glib-2.0 gio-2.0 gobject-2.0 Libs: -L${libdir} -lconsolekit Cflags: -I${includedir}/ConsoleKit/ consolekit2-1.2.6/libconsolekit/sd-compat.c000066400000000000000000000115541446640754400206740ustar00rootroot00000000000000#include "config.h" #include #include #include #include #include #include #include "libconsolekit.h" int sd_session_get_class(const char *session, char **class) { LibConsoleKit *ck = NULL; GError *error = NULL; ck = lib_consolekit_new (); lib_consolekit_session_get_class (ck, session, class, &error); if (error) { g_warning ("Unable to determine session class: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return 0; } int sd_session_get_seat(const char *session, char **seat) { LibConsoleKit *ck = NULL; GError *error = NULL; ck = lib_consolekit_new (); lib_consolekit_session_get_seat (ck, session, seat, &error); if (error) { g_warning ("Unable to determine seat: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return 0; } int sd_session_get_type(const char *session, char **type) { LibConsoleKit *ck = NULL; GError *error = NULL; ck = lib_consolekit_new (); lib_consolekit_session_get_type (ck, session, type, &error); if (error) { g_warning ("Unable to determine seat type: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return 0; } int sd_session_get_state(const char *session, char **state) { LibConsoleKit *ck = NULL; GError *error = NULL; ck = lib_consolekit_new (); lib_consolekit_session_get_state (ck, session, state, &error); if (error) { g_warning ("Unable to determine seat state: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return 0; } int sd_session_get_uid(const char *session, uid_t *uid) { LibConsoleKit *ck = NULL; GError *error = NULL; ck = lib_consolekit_new (); lib_consolekit_session_get_uid (ck, session, uid, &error); if (error) { g_warning ("Unable to determine session uid: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return 0; } int sd_session_get_service(const char *session, char **service) { LibConsoleKit *ck = NULL; GError *error = NULL; ck = lib_consolekit_new (); lib_consolekit_session_get_service (ck, session, service, &error); if (error) { g_warning ("Unable to determine session service: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return 0; } int sd_pid_get_session(pid_t pid, char **session) { LibConsoleKit *ck = NULL; GError *error = NULL; int ret = 0; ck = lib_consolekit_new (); ret = lib_consolekit_pid_get_session (ck, pid, session, &error); if (error) { g_warning ("Unable to determine list of session for pid: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return ret; } int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) { LibConsoleKit *ck = NULL; GError *error = NULL; int ret = 0; ck = lib_consolekit_new (); ret = lib_consolekit_uid_get_sessions (ck, uid, sessions, &error); if (error) { g_warning ("Unable to determine session uid: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return ret; } int sd_seat_can_graphical(const char *seat) { // XXX return 1; } int sd_seat_can_multi_session(const char *seat) { LibConsoleKit *ck = NULL; GError *error = NULL; gboolean can_activate = FALSE; ck = lib_consolekit_new (); can_activate = lib_consolekit_seat_can_multi_session (ck, seat, &error); if (error) { g_warning ("Unable to determine if seat can activate sessions: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return FALSE; } g_object_unref (ck); return can_activate; } int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned int *n_uids) { LibConsoleKit *ck = NULL; GError *error = NULL; int num_sessions; ck = lib_consolekit_new (); num_sessions = lib_consolekit_seat_get_sessions (ck, seat, sessions, &error); if (error) { g_warning ("Unable to determine if seat can activate sessions: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return FALSE; } g_object_unref (ck); return num_sessions; } int sd_get_sessions(char ***sessions) { LibConsoleKit *ck = NULL; GError *error = NULL; int ret = 0; ck = lib_consolekit_new (); ret = lib_consolekit_get_sessions (ck, sessions, &error); if (error) { g_warning ("Unable to get sessions: %s", error ? error->message : ""); g_error_free (error); g_object_unref (ck); return -ENXIO; } g_object_unref (ck); return ret; } consolekit2-1.2.6/libconsolekit/sd-login.h000066400000000000000000000013511446640754400205200ustar00rootroot00000000000000#include int sd_session_get_class(const char *session, char **class); int sd_session_get_seat(const char *session, char **seat); int sd_session_get_type(const char *session, char **type); int sd_session_get_state(const char *session, char **state); int sd_session_get_uid(const char *session, uid_t *uid); int sd_session_get_service(const char *session, char **service); int sd_pid_get_session(pid_t pid, char **session); int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions); int sd_seat_can_graphical(const char *seat); int sd_seat_can_multi_session(const char *seat); int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned int *n_uids); int sd_get_sessions(char ***sessions); consolekit2-1.2.6/libconsolekit/test-libconsolekit.c000066400000000000000000000274331446640754400226260ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2017, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include "libconsolekit.h" static void test_seat_get_active (LibConsoleKit *ck, const gchar *seat) { gchar *session = NULL; uid_t uid = 0; GError *error = NULL; /* try it with all the defaults */ lib_consolekit_seat_get_active (ck, seat, &session, &uid, &error); if (!error) { g_print ("lib_consolekit_seat_get_active (seat %s) : session %s uid %d\n", seat, session, uid); } else { g_print ("lib_consolekit_seat_get_active (seat %s) : error %s\n", seat, error->message); g_clear_error (&error); } /* try it without the UID */ lib_consolekit_seat_get_active (ck, seat, &session, NULL, &error); if (!error) { g_print ("lib_consolekit_seat_get_active (seat %s) : session %s ignoring uid\n", seat, session); } else { g_print ("lib_consolekit_seat_get_active (seat %s) : error %s\n", seat, error->message); g_clear_error (&error); } g_free (session); } static void test_seat_get_sessions (LibConsoleKit *ck, const gchar *seat) { gchar **sessions = NULL; gint num_sessions; gint i; GError *error = NULL; num_sessions = lib_consolekit_seat_get_sessions (ck, seat, &sessions, &error); if (!error) { g_print ("lib_consolekit_seat_get_sessions (seat %s) : number of sessions %d\n", seat, num_sessions); for (i = 0; i < num_sessions && num_sessions > 0; i++) { g_print ("lib_consolekit_seat_get_sessions (seat %s) : session %s\n", seat, sessions[i]); } } else { g_print ("lib_consolekit_seat_get_sessions (seat %s) : error %s\n", seat, error->message); g_clear_error (&error); } g_strfreev (sessions); } static void test_seat_can_multisession (LibConsoleKit *ck, const gchar *seat) { gboolean can_multisession; GError *error = NULL; can_multisession = lib_consolekit_seat_can_multi_session (ck, seat, &error); if (!error) { g_print ("lib_consolekit_seat_can_multi_session (seat %s) : %s\n", seat, can_multisession ? "TRUE" : "FALSE"); } else { g_print ("lib_consolekit_seat_can_multi_session (seat %s) : error %s\n", seat, error->message); g_clear_error (&error); } } static void test_session_is_active (LibConsoleKit *ck, const gchar *session) { gboolean is_active; GError *error = NULL; is_active = lib_consolekit_session_is_active (ck, session, &error); if (!error) { g_print ("lib_consolekit_session_is_active (session %s) : %s\n", session, is_active ? "TRUE" : "FALSE"); } else { g_print ("lib_consolekit_session_is_active (session %s) : error %s\n", session, error->message); g_clear_error (&error); } } static void test_session_is_remote (LibConsoleKit *ck, const gchar *session) { gboolean is_remote; GError *error = NULL; is_remote = lib_consolekit_session_is_remote (ck, session, &error); if (!error) { g_print ("lib_consolekit_session_is_remote (session %s) : %s\n", session, is_remote ? "TRUE" : "FALSE"); } else { g_print ("lib_consolekit_session_is_remote (session %s) : error %s\n", session, error->message); g_clear_error (&error); } } static void test_session_get_uid (LibConsoleKit *ck, const gchar *session) { guint uid; GError *error = NULL; lib_consolekit_session_get_uid (ck, session, &uid, &error); if (!error) { g_print ("lib_consolekit_session_get_uid (session %s) : uid %d\n", session, uid); } else { g_print ("lib_consolekit_session_get_uid (session %s) : error %s\n", session, error->message); g_clear_error (&error); } } static void test_session_get_seat (LibConsoleKit *ck, const gchar *session) { gchar *seat = NULL; GError *error = NULL; lib_consolekit_session_get_seat (ck, session, &seat, &error); if (!error) { g_print ("lib_consolekit_session_get_seat (session %s) : seat %s\n", session, seat); } else { g_print ("lib_consolekit_session_get_seat (session %s) : error %s\n", session, error->message); g_clear_error (&error); } g_free (seat); } static void test_session_get_display (LibConsoleKit *ck, const gchar *session) { gchar *display = NULL; GError *error = NULL; lib_consolekit_session_get_display (ck, session, &display, &error); if (!error) { g_print ("lib_consolekit_session_get_display (session %s) : display %s\n", session, display); } else { g_print ("lib_consolekit_session_get_display (session %s) : error %s\n", session, error->message); g_clear_error (&error); } g_free (display); } static void test_session_get_remote_host (LibConsoleKit *ck, const gchar *session) { gchar *hostname = NULL; GError *error = NULL; lib_consolekit_session_get_remote_host (ck, session, &hostname, &error); if (!error) { g_print ("lib_consolekit_session_get_remote_host (session %s) : hostname %s\n", session, hostname); } else { g_print ("lib_consolekit_session_get_remote_host (session %s) : error %s\n", session, error->message); g_clear_error (&error); } g_free (hostname); } static void test_session_get_type (LibConsoleKit *ck, const gchar *session) { gchar *type = NULL; GError *error = NULL; lib_consolekit_session_get_type (ck, session, &type, &error); if (!error) { g_print ("lib_consolekit_session_get_type (session %s) : session type %s\n", session, type); } else { g_print ("lib_consolekit_session_get_type (session %s) : error %s\n", session, error->message); g_clear_error (&error); } g_free (type); } static void test_session_get_class (LibConsoleKit *ck, const gchar *session) { gchar *session_class = NULL; GError *error = NULL; lib_consolekit_session_get_class (ck, session, &session_class, &error); if (!error) { g_print ("lib_consolekit_session_get_class (session %s) : session class %s\n", session, session_class); } else { g_print ("lib_consolekit_session_get_class (session %s) : error %s\n", session, error->message); g_clear_error (&error); } g_free (session_class); } static void test_session_get_state (LibConsoleKit *ck, const gchar *session) { gchar *state = NULL; GError *error = NULL; lib_consolekit_session_get_state (ck, session, &state, &error); if (!error) { g_print ("lib_consolekit_session_get_state (session %s) : session state %s\n", session, state); } else { g_print ("lib_consolekit_session_get_state (session %s) : error %s\n", session, error->message); g_clear_error (&error); } g_free (state); } static void test_session_get_tty (LibConsoleKit *ck, const gchar *session) { gchar *tty = NULL; GError *error = NULL; lib_consolekit_session_get_tty (ck, session, &tty, &error); if (!error) { g_print ("lib_consolekit_session_get_tty (session %s) : tty %s\n", session, tty); } else { g_print ("lib_consolekit_session_get_tty (session %s) : error %s\n", session, error->message); g_clear_error (&error); } g_free (tty); } static void test_session_get_vt (LibConsoleKit *ck, const gchar *session) { guint vt; GError *error = NULL; lib_consolekit_session_get_vt (ck, session, &vt, &error); if (!error) { g_print ("lib_consolekit_session_get_vt (session %s) : vt %d\n", session, vt); } else { g_print ("lib_consolekit_session_get_vt (session %s) : error %s\n", session, error->message); g_clear_error (&error); } } static void test_pid_get_session (LibConsoleKit *ck, gint pid) { gchar *session = NULL; GError *error = NULL; lib_consolekit_pid_get_session (ck, pid, &session, &error); if (!error) { g_print ("lib_consolekit_pid_get_session (pid %d) : session %s\n", pid, session); } else { g_print ("lib_consolekit_pid_get_session (pid %d) : error %s\n", pid, error->message); g_clear_error (&error); } g_free (session); } gchar *opt_seat = "/org/freedesktop/ConsoleKit/seat0"; gchar *opt_session = "/org/freedesktop/ConsoleKit/Session2"; gint opt_pid = 0; static GOptionEntry option_entries[] = { { "seat", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &opt_seat, "Specify seat to use in queries", NULL }, { "session", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &opt_session, "Specify session to use in queries", NULL }, { "pid", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT, &opt_pid, "Specify process id to use in queries", NULL }, { NULL } }; int main (int argc, char *argv[]) { LibConsoleKit *ck = NULL; GError *error = NULL; GOptionContext *context; g_setenv ("G_DEBUG", "fatal_criticals", FALSE); g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); context = g_option_context_new (""); g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_print ("option parsing failed: %s\n", error->message); exit (1); } if (opt_pid <= 0) { opt_pid = getpid (); } ck = lib_consolekit_new (); test_seat_get_active (ck, opt_seat); test_seat_get_sessions (ck, opt_seat); test_seat_can_multisession (ck, opt_seat); test_session_is_active (ck, opt_session); test_session_is_remote (ck, opt_session); test_session_get_uid (ck, opt_session); test_session_get_seat (ck, opt_session); test_session_get_display (ck, opt_session); test_session_get_remote_host (ck, opt_session); test_session_get_type (ck, opt_session); test_session_get_class (ck, opt_session); test_session_get_state (ck, opt_session); test_session_get_tty (ck, opt_session); test_session_get_vt (ck, opt_session); test_pid_get_session (ck, opt_pid); g_object_unref (ck); g_option_context_free (context); return 0; } consolekit2-1.2.6/m4/000077500000000000000000000000001446640754400143125ustar00rootroot00000000000000consolekit2-1.2.6/m4/introspection.m4000066400000000000000000000067341446640754400174660ustar00rootroot00000000000000dnl -*- mode: autoconf -*- dnl Copyright 2009 Johan Dahlin dnl dnl This file is free software; the author(s) gives unlimited dnl permission to copy and/or distribute it, with or without dnl modifications, as long as this notice is preserved. dnl # serial 1 m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], [ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([LT_INIT],[$0])dnl setup libtool first dnl enable/disable introspection m4_if([$2], [require], [dnl enable_introspection=yes ],[dnl AC_ARG_ENABLE(introspection, AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], [Enable introspection for this build]),, [enable_introspection=auto]) ])dnl AC_MSG_CHECKING([for gobject-introspection]) dnl presence/version checking AS_CASE([$enable_introspection], [no], [dnl found_introspection="no (disabled, use --enable-introspection to enable)" ],dnl [yes],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0],, AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) ],dnl [auto],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) dnl Canonicalize enable_introspection enable_introspection=$found_introspection ],dnl [dnl AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) ])dnl AC_MSG_RESULT([$found_introspection]) INTROSPECTION_SCANNER= INTROSPECTION_COMPILER= INTROSPECTION_GENERATE= INTROSPECTION_GIRDIR= INTROSPECTION_TYPELIBDIR= if test "x$found_introspection" = "xyes"; then INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection fi AC_SUBST(INTROSPECTION_SCANNER) AC_SUBST(INTROSPECTION_COMPILER) AC_SUBST(INTROSPECTION_GENERATE) AC_SUBST(INTROSPECTION_GIRDIR) AC_SUBST(INTROSPECTION_TYPELIBDIR) AC_SUBST(INTROSPECTION_CFLAGS) AC_SUBST(INTROSPECTION_LIBS) AC_SUBST(INTROSPECTION_MAKEFILE) AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") ]) dnl Usage: dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) ]) dnl Usage: dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) ]) consolekit2-1.2.6/m4/xdt-depends.m4000066400000000000000000000245721446640754400170050ustar00rootroot00000000000000dnl Copyright (c) 2002-2015 dnl The Xfce development team. All rights reserved. dnl dnl Written for Xfce by Benedikt Meurer . dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License along dnl with this program; if not, write to the Free Software Foundation, Inc., dnl 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. dnl dnl xdt-depends dnl ----------- dnl Contains M4 macros to check for software dependencies. dnl Partly based on prior work of the XDG contributors. dnl dnl We need recent a autoconf version AC_PREREQ([2.60]) dnl XDT_PROG_PKG_CONFIG() dnl dnl Checks for the freedesktop.org pkg-config dnl utility and sets the PKG_CONFIG environment dnl variable to the full path if found. dnl AC_DEFUN([XDT_PROG_PKG_CONFIG], [ # minimum supported version of pkg-config xdt_cv_PKG_CONFIG_MIN_VERSION=0.9.0 m4_ifdef([PKG_PROG_PKG_CONFIG], [ PKG_PROG_PKG_CONFIG([$xdt_cv_PKG_CONFIG_MIN_VERSION]) if test x"$PKG_CONFIG" = x""; then echo echo "*** Your version of pkg-config is too old. You need atleast" echo "*** pkg-config $xdt_cv_PKG_CONFIG_MIN_VERSION or newer. You can download pkg-config" echo "*** from the freedesktop.org software repository at" echo "***" echo "*** http://www.freedesktop.org/software/pkgconfig" echo "***" exit 1; fi ], [ echo echo "*** The pkg-config utility could not be found on your system." echo "*** Make sure it is in your path, or set the PKG_CONFIG" echo "*** environment variable to the full path to pkg-config." echo "*** You can download pkg-config from the freedesktop.org" echo "*** software repository at" echo "***" echo "*** http://www.freedesktop.org/software/pkgconfig" echo "***" exit 1 ]) ]) dnl XDT_CHECK_PACKAGE(varname, package, version, [action-if], [action-if-not]) dnl dnl Checks if "package" >= "version" is installed on the dnl target system, using the pkg-config utility. If the dnl dependency is met, "varname"_CFLAGS, "varname"_LIBS, dnl "varname"_VERSION and "varname"_REQUIRED_VERSION dnl will be set and marked for substition. dnl dnl "varname"_REQUIRED_VERSION will be set to the value of dnl "version". This is mostly useful to automatically dnl place the correct version information into the RPM dnl .spec file. dnl dnl In addition, if the dependency is met, "action-if" will dnl be executed if given. dnl dnl If the package check fails, "action-if-not" will be dnl executed. If this parameter isn't specified, a diagnostic dnl message will be printed and the configure script will dnl be terminated with exit code 1. dnl AC_DEFUN([XDT_CHECK_PACKAGE], [ XDT_PROG_PKG_CONFIG() AC_MSG_CHECKING([for $2 >= $3]) if $PKG_CONFIG "--atleast-version=$3" "$2" >/dev/null 2>&1; then $1_VERSION=`$PKG_CONFIG --modversion "$2"` AC_MSG_RESULT([$$1_VERSION]) AC_MSG_CHECKING([$1_CFLAGS]) $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` AC_MSG_RESULT([$$1_CFLAGS]) AC_MSG_CHECKING([$1_LIBS]) $1_LIBS=`$PKG_CONFIG --libs "$2"` AC_MSG_RESULT([$$1_LIBS]) $1_REQUIRED_VERSION=$3 AC_SUBST([$1_VERSION]) AC_SUBST([$1_CFLAGS]) AC_SUBST([$1_LIBS]) AC_SUBST([$1_REQUIRED_VERSION]) ifelse([$4], , , [$4]) elif $PKG_CONFIG --exists "$2" >/dev/null 2>&1; then xdt_cv_version=`$PKG_CONFIG --modversion "$2"` AC_MSG_RESULT([found, but $xdt_cv_version]) ifelse([$5], , [ echo "*** The required package $2 was found on your system," echo "*** but the installed version ($xdt_cv_version) is too old." echo "*** Please upgrade $2 to atleast version $3, or adjust" echo "*** the PKG_CONFIG_PATH environment variable if you installed" echo "*** the new version of the package in a nonstandard prefix so" echo "*** pkg-config is able to find it." exit 1 ], [$5]) else AC_MSG_RESULT([not found]) ifelse([$5], , [ echo "*** The required package $2 was not found on your system." echo "*** Please install $2 (atleast version $3) or adjust" echo "*** the PKG_CONFIG_PATH environment variable if you" echo "*** installed the package in a nonstandard prefix so that" echo "*** pkg-config is able to find it." exit 1 ], [$5]) fi ]) dnl XDT_CHECK_OPTIONAL_PACKAGE(varname, package, version, optionname, helpstring, [default]) dnl dnl Checks for an optional dependency on "package" >= "version". "default" dnl can be "yes" or "no" (defaults to "yes" if not specified) and controls dnl whether configure should check this dependency by default, or only if dnl the user explicitly enables it using a command line switch. dnl dnl This macro automatically adds a commandline switch based on the "optionname" dnl parameter (--enable-optionname/--disable-optionname), which allows the dnl user to explicitly control whether this optional dependency should be dnl enabled or not. The "helpstring" parameter gives a brief(!) description dnl about this dependency. dnl dnl If the user chose to enable this dependency and the required package dnl was found, this macro defines the variable "varname"_FOUND and sets it dnl to the string "yes", in addition to the 4 variables set by XDT_CHECK_PACKAGE. dnl But "varname"_FOUND will not be marked for substition. Furthermore, dnl a CPP define HAVE_"varname" will be placed in config.h (or added to dnl the cc command line, depending on your configure.ac) and set to dnl 1. dnl AC_DEFUN([XDT_CHECK_OPTIONAL_PACKAGE], [ AC_REQUIRE([XDT_PROG_PKG_CONFIG]) AC_ARG_ENABLE([$4], AC_HELP_STRING([--enable-$4], [Enable checking for $5 (default=m4_default([$6], [yes]))]) AC_HELP_STRING([--disable-$4], [Disable checking for $5]), [xdt_cv_$1_check=$enableval], [xdt_cv_$1_check=m4_default([$6], [yes])]) if test x"$xdt_cv_$1_check" = x"yes"; then if $PKG_CONFIG --exists "$2 >= $3" >/dev/null 2>&1; then XDT_CHECK_PACKAGE([$1], [$2], [$3], [ AC_DEFINE([HAVE_$1], [1], [Define if $2 >= $3 present]) $1_FOUND="yes" ]) else AC_MSG_CHECKING([for optional package $2 >= $3]) AC_MSG_RESULT([not found]) fi else AC_MSG_CHECKING([for optional package $2]) AC_MSG_RESULT([disabled]) fi AM_CONDITIONAL([HAVE_$1], [test x"$$1_FOUND" = x"yes"]) ]) dnl XDT_CHECK_LIBX11() dnl dnl Executes various checks for X11. Sets LIBX11_CFLAGS, LIBX11_LDFLAGS dnl and LIBX11_LIBS (and marks them for substitution). In addition dnl HAVE_LIBX11 is set to 1 in config.h, if the X window system and dnl the development files are detected on the target system. dnl AC_DEFUN([XDT_CHECK_LIBX11], [ AC_REQUIRE([AC_PATH_XTRA]) LIBX11_CFLAGS= LIBX11_LDFLAGS= LIBX11_LIBS= if test x"$no_x" != x"yes"; then AC_CHECK_LIB([X11], [main], [ AC_DEFINE([HAVE_LIBX11], [1], [Define if libX11 is available]) LIBX11_CFLAGS="$X_CFLAGS" for option in $X_PRE_LIBS $X_EXTRA_LIBS $X_LIBS; do case "$option" in -L*) path=`echo $option | sed 's/^-L//'` if test x"$path" != x""; then LIBX11_LDFLAGS="$LIBX11_LDFLAGS -L$path" fi ;; *) LIBX11_LIBS="$LIBX11_LIBS $option" ;; esac done if ! echo $LIBX11_LIBS | grep -- '-lX11' >/dev/null; then LIBX11_LIBS="$LIBX11_LIBS -lX11" fi ], [], [$X_CFLAGS $X_PRE_LIBS $X_EXTRA_LIBS $X_LIBS]) fi AC_SUBST([LIBX11_CFLAGS]) AC_SUBST([LIBX11_LDFLAGS]) AC_SUBST([LIBX11_LIBS]) ]) dnl XDT_CHECK_LIBX11_REQUIRE() dnl dnl Similar to XDT_CHECK_LIBX11(), but terminates with an error if dnl the X window system and development files aren't detected on the dnl target system. dnl AC_DEFUN([XDT_CHECK_LIBX11_REQUIRE], [ AC_REQUIRE([XDT_CHECK_LIBX11]) if test x"$no_x" = x"yes"; then AC_MSG_ERROR([X Window system libraries and header files are required]) fi ]) dnl XDT_CHECK_LIBSM() dnl dnl Checks whether the session management library is present on the dnl target system, and sets LIBSM_CFLAGS, LIBSM_LDFLAGS and LIBSM_LIBS dnl properly. In addition, HAVE_LIBSM will be set to 1 in config.h dnl if libSM is detected. dnl AC_DEFUN([XDT_CHECK_LIBSM], [ AC_REQUIRE([XDT_CHECK_LIBX11]) LIBSM_CFLAGS= LIBSM_LDFLAGS= LIBSM_LIBS= if test x"$no_x" != x"yes"; then AC_CHECK_LIB([SM], [SmcSaveYourselfDone], [ AC_DEFINE([HAVE_LIBSM], [1], [Define if libSM is available]) LIBSM_CFLAGS="$LIBX11_CFLAGS" LIBSM_LDFLAGS="$LIBX11_LDFLAGS" LIBSM_LIBS="$LIBX11_LIBS" if ! echo $LIBSM_LIBS | grep -- '-lSM' >/dev/null; then LIBSM_LIBS="$LIBSM_LIBS -lSM -lICE" fi ], [], [$LIBX11_CFLAGS $LIBX11_LDFLAGS $LIBX11_LIBS -lICE]) fi AC_SUBST([LIBSM_CFLAGS]) AC_SUBST([LIBSM_LDFLAGS]) AC_SUBST([LIBSM_LIBS]) ]) dnl XDT_CHECK_LIBXPM() dnl dnl Checks if the Xpm library is present on the target system, and dnl sets LIBXPM_CFLAGS, LIBXPM_LDFLAGS and LIBXPM_LIBS. In addition, dnl HAVE_LIBXPM will be set to 1 in config.h if libXpm is detected. dnl AC_DEFUN([XDT_CHECK_LIBXPM], [ AC_REQUIRE([XDT_CHECK_LIBX11]) LIBXPM_CFLAGS= LIBXPM_LDFLAGS= LIBXPM_LIBS= if test "$no_x" != "yes"; then AC_CHECK_LIB([Xpm], [main], [ AC_DEFINE([HAVE_LIBXPM], [1], [Define if libXpm is available]) LIBXPM_CFLAGS="$LIBX11_CFLAGS" LIBXPM_LDFLAGS="$LIBX11_LDFLAGS" LIBXPM_LIBS="$LIBX11_LIBS" if ! echo $LIBXPM_LIBS | grep -- '-lXpm' >/dev/null; then LIBXPM_LIBS="$LIBXPM_LIBS -lXpm" fi ], [], [$LIBX11_CFLAGS $LIBX11_LDFLAGS $LIBX11_LIBS -lXpm]) fi AC_SUBST([LIBXPM_CFLAGS]) AC_SUBST([LIBXPM_LDFLAGS]) AC_SUBST([LIBXPM_LIBS]) ]) dnl XDT_CHECK_LIBXPM_REQUIRE() dnl dnl Similar to XDT_CHECK_LIBXPM(), but fails if the Xpm library isn't dnl present on the target system. dnl AC_DEFUN([XDT_CHECK_LIBXPM_REQUIRE], [ AC_REQUIRE([XDT_CHECK_LIBX11_REQUIRE]) AC_REQUIRE([XDT_CHECK_LIBXPM]) if test x"$LIBXPM_LIBS" = x""; then AC_MSG_ERROR([The Xpm library was not found on your system]) fi ]) consolekit2-1.2.6/m4/xdt-features.m4000066400000000000000000000161761446640754400172020ustar00rootroot00000000000000dnl Copyright (c) 2002-2015 dnl The Xfce development team. All rights reserved. dnl dnl Written for Xfce by Benedikt Meurer . dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License along dnl with this program; if not, write to the Free Software Foundation, Inc., dnl 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. dnl dnl xdt-depends dnl ----------- dnl Contains M4 macros to check for software dependencies. dnl Partly based on prior work of the XDG contributors. dnl dnl We need recent a autoconf version AC_PREREQ([2.60]) dnl XDT_SUPPORTED_FLAGS(VAR, FLAGS) dnl dnl For each token in FLAGS, checks to be sure the compiler supports dnl the flag, and if so, adds each one to VAR. dnl AC_DEFUN([XDT_SUPPORTED_FLAGS], [ for flag in $2; do AC_MSG_CHECKING([if $CC supports $flag]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $flag" AC_COMPILE_IFELSE([AC_LANG_SOURCE([ ])], [flag_supported=yes], [flag_supported=no]) CFLAGS="$saved_CFLAGS" AC_MSG_RESULT([$flag_supported]) if test "x$flag_supported" = "xyes"; then $1="$$1 $flag" fi done ]) dnl XDT_FEATURE_DEBUG(default_level=minimum) dnl AC_DEFUN([XDT_FEATURE_DEBUG], [ dnl weird indentation to keep output indentation correct AC_ARG_ENABLE([debug], AC_HELP_STRING([--enable-debug@<:@=no|minimum|yes|full@:>@], [Build with debugging support @<:@default=m4_default([$1], [minimum])@:>@]) AC_HELP_STRING([--disable-debug], [Include no debugging support]), [enable_debug=$enableval], [enable_debug=m4_default([$1], [minimum])]) AC_MSG_CHECKING([whether to build with debugging support]) if test x"$enable_debug" = x"full" -o x"$enable_debug" = x"yes"; then AC_DEFINE([DEBUG], [1], [Define for debugging support]) xdt_cv_additional_CFLAGS="-DXFCE_DISABLE_DEPRECATED \ -Wall -Wextra \ -Wno-missing-field-initializers \ -Wno-unused-parameter -Wold-style-definition \ -Wdeclaration-after-statement \ -Wmissing-declarations \ -Wmissing-noreturn -Wpointer-arith \ -Wcast-align -Wformat -Wformat-security -Wformat-y2k \ -Winit-self -Wmissing-include-dirs -Wundef \ -Wnested-externs" CPPFLAGS="$CPPFLAGS" if test x`uname` = x"Linux"; then xdt_cv_additional_CFLAGS="$xdt_cv_additional_CFLAGS -fstack-protector" fi dnl # signal.h inline is crapy on openbsd if test x`uname` != x"OpenBSD"; then xdt_cv_additional_CFLAGS="$xdt_cv_additional_CFLAGS" fi if test x"$enable_debug" = x"full"; then AC_DEFINE([CONSOLEKIT_DEBUGGING], [1], [Define for full ConsoleKit debugging support]) xdt_cv_additional_CFLAGS="$xdt_cv_additional_CFLAGS -O0 -g -Werror" CPPFLAGS="$CPPFLAGS -DG_ENABLE_DEBUG" AC_MSG_RESULT([full]) else xdt_cv_additional_CFLAGS="$xdt_cv_additional_CFLAGS -g -Wshadow" AC_MSG_RESULT([yes]) fi XDT_SUPPORTED_FLAGS([supported_CFLAGS], [$xdt_cv_additional_CFLAGS]) ifelse([$CXX], , , [ dnl FIXME: should test on c++ compiler, but the following line causes dnl autoconf errors for projects that don't check for a dnl c++ compiler at all. dnl AC_LANG_PUSH([C++]) dnl XDT_SUPPORTED_FLAGS([supported_CXXFLAGS], [$xdt_cv_additional_CFLAGS]) dnl AC_LANG_POP() dnl instead, just use supported_CFLAGS... supported_CXXFLAGS="$supported_CFLAGS" ]) CFLAGS="$CFLAGS $supported_CFLAGS" CXXFLAGS="$CXXFLAGS $supported_CXXFLAGS" else CPPFLAGS="$CPPFLAGS -DNDEBUG" if test x"$enable_debug" = x"no"; then CPPFLAGS="$CPPFLAGS -DG_DISABLE_CAST_CHECKS -DG_DISABLE_ASSERT" AC_MSG_RESULT([no]) else AC_MSG_RESULT([minimum]) fi fi ]) dnl XDT_FEATURE_VISIBILITY() dnl dnl Checks to see if the compiler supports the 'visibility' attribute dnl If so, adds -DHAVE_GNUC_VISIBILTY to CPPFLAGS. Also sets the dnl automake conditional HAVE_GNUC_VISIBILITY. dnl AC_DEFUN([XDT_FEATURE_VISIBILITY], [ AC_ARG_ENABLE([visibility], AC_HELP_STRING([--disable-visibility], [Don't use ELF visibility attributes]), [enable_visibility=$enableval], [enable_visibility=yes]) have_gnuc_visibility=no if test "x$enable_visibility" != "xno"; then XDT_SUPPORTED_FLAGS([xdt_vis_test_cflags], [-Wall -Werror -Wno-unused-parameter]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $xdt_vis_test_cflags" AC_MSG_CHECKING([whether $CC supports the GNUC visibility attribute]) AC_COMPILE_IFELSE([AC_LANG_SOURCE( [ void test_default (void); void test_hidden (void); void __attribute__ ((visibility("default"))) test_default (void) {} void __attribute__ ((visibility("hidden"))) test_hidden (void) {} int main (int argc, char **argv) { test_default (); test_hidden (); return 0; } ])], [ have_gnuc_visibility=yes AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) CFLAGS="$saved_CFLAGS" fi if test "x$have_gnuc_visibility" = "xyes"; then CPPFLAGS="$CPPFLAGS -DHAVE_GNUC_VISIBILITY" xdt_vis_hidden_cflags="" XDT_SUPPORTED_FLAGS([xdt_vis_hidden_cflags], [-xldscope=hidden]) if test "x$xdt_vis_hidden_cflags" = "x"; then XDT_SUPPORTED_FLAGS([xdt_vis_hidden_cflags], [-fvisibility=hidden]) fi CFLAGS="$CFLAGS $xdt_vis_hidden_cflags" fi AM_CONDITIONAL([HAVE_GNUC_VISIBILITY], [test "x$have_gnuc_visibility" = "xyes"]) ]) dnl XDT_FEATURE_LINKER_OPTS dnl dnl Checks for and enables any special linker optimizations. dnl AC_DEFUN([XDT_FEATURE_LINKER_OPTS], [ AC_ARG_ENABLE([linker-opts], AC_HELP_STRING([--disable-linker-opts], [Disable linker optimizations]), [enable_linker_opts=$enableval], [enable_linker_opts=yes]) if test "x$enable_linker_opts" != "xno"; then if test x`uname` != x"OpenBSD"; then AC_MSG_CHECKING([whether $LD accepts --as-needed]) case `$LD --as-needed -v 2>&1 &1 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif /* HAVE_PATHS_H */ #ifndef _PATH_DEV #define _PATH_DEV "/dev/" #endif #define PAM_SM_SESSION #include #include #ifdef HAVE_SECURITY_PAM_MODUTIL_H #include #endif #ifdef HAVE_SECURITY_PAM_EXT_H #include #endif #include "ck-connector.h" static int opt_debug = FALSE; static int opt_nox11 = FALSE; #ifndef HAVE_PAM_SYSLOG #ifndef LOG_AUTHPRIV #define LOG_AUTHPRIV LOG_AUTH #endif #ifndef PAM_EXTERN #ifdef PAM_STATIC #define PAM_EXTERN static #else #define PAM_EXTERN extern #endif #endif static void ck_pam_vsyslog (const pam_handle_t *pamh, int priority, const char *fmt, va_list args) { char msgbuf1 [1024]; char msgbuf2 [1024]; int save_errno; const char *service; const char *mod_name; const char *choice; int res; save_errno = errno; mod_name = "pam_ck_connector"; choice = "session"; if (pamh != NULL) { res = pam_get_item (pamh, PAM_SERVICE, (void *) &service); if (service == NULL || *service == '\0' || res != PAM_SUCCESS) { service = ""; } } else { service = ""; } res = snprintf (msgbuf1, sizeof (msgbuf1), "%s(%s:%s):", mod_name, service, choice); if (res < 0) { return; } errno = save_errno; res = vsnprintf (msgbuf2, sizeof (msgbuf2), fmt, args); if (res < 0) { return; } errno = save_errno; syslog (LOG_AUTHPRIV|priority, "%s %s", msgbuf1, msgbuf2); } static void ck_pam_syslog (const pam_handle_t *pamh, int priority, const char *fmt, ...) { va_list args; va_start (args, fmt); ck_pam_vsyslog (pamh, priority, fmt, args); va_end (args); } #else #define ck_pam_syslog(pamh, priority, ...) pam_syslog(pamh, priority, __VA_ARGS__) #endif static void _parse_pam_args (const pam_handle_t *pamh, int flags, int argc, const char **argv) { int i; opt_debug = FALSE; for (i = 0; i < argc && argv[i] != NULL; i++) { if (strcmp (argv[i] , "debug") == 0) { opt_debug = TRUE; } else if (strcmp (argv[i] , "nox11") == 0) { opt_nox11 = TRUE; } else { ck_pam_syslog (pamh, LOG_ERR, "unknown option: %s", argv[i]); } } } PAM_EXTERN int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; } PAM_EXTERN int pam_sm_setcred (pam_handle_t *pamh, int flags, int argc, const char **argv) { return PAM_IGNORE; } static uid_t _util_name_to_uid (const char *username, gid_t *default_gid) { int rc; uid_t res; char *buf = NULL; long bufsize; struct passwd pwd; struct passwd *pwdp; res = (uid_t) -1; bufsize = sysconf (_SC_GETPW_R_SIZE_MAX); if (bufsize == -1) { // assume 1024, not all systems (e.g musl) have _SC_GETPW_R_SIZE_MAX bufsize = 1024; } buf = calloc (sizeof (char), bufsize); rc = getpwnam_r (username, &pwd, buf, bufsize, &pwdp); if (rc != 0 || pwdp == NULL) { goto out; } res = pwdp->pw_uid; if (default_gid != NULL) { *default_gid = pwdp->pw_gid; } out: free (buf); return res; } /* our singleton */ static CkConnector *ckc = NULL; PAM_EXTERN int pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, const char **argv) { if (ckc != NULL) { ck_connector_unref (ckc); ckc = NULL; } return PAM_SUCCESS; } PAM_EXTERN int pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char **argv) { int ret; int res; const char *user; const char *display_device; const char *x11_display; const char *x11_display_device; const char *remote_host_name; const char *runtime_dir; const char *s; uid_t uid; char buf[256]; char *ttybuf; char *xdd; DBusError error; dbus_bool_t is_local; ret = PAM_IGNORE; ttybuf = NULL; xdd = NULL; is_local = TRUE; _parse_pam_args (pamh, flags, argc, argv); /* Register with ConsoleKit as part of the session management */ if (ckc != NULL) { ck_pam_syslog (pamh, LOG_ERR, "process already registered with ConsoleKit"); goto out; } /* set a global flag so that D-Bus does not change the SIGPIPE handler. See https://bugzilla.redhat.com/show_bug.cgi?id=430431 */ dbus_connection_set_change_sigpipe (FALSE); ckc = ck_connector_new (); if (ckc == NULL) { ck_pam_syslog (pamh, LOG_ERR, "oom creating ConsoleKit connector object"); goto out; } user = NULL; res = pam_get_user (pamh, &user, NULL); if (res != PAM_SUCCESS || user == NULL || user[0] == '\0') { ck_pam_syslog (pamh, LOG_ERR, "cannot determine username"); goto out; } display_device = NULL; res = pam_get_item (pamh, PAM_TTY, (const void **) &display_device); if (res != PAM_SUCCESS || display_device == NULL || display_device[0] == '\0') { ck_pam_syslog (pamh, LOG_ERR, "cannot determine display-device"); goto out; } x11_display = NULL; /* interpret any tty with a colon as a DISPLAY */ if (strchr (display_device, ':') != NULL) { if (opt_nox11) { ck_pam_syslog (pamh, LOG_WARNING, "nox11 mode, ignoring PAM_TTY %s", display_device); goto out; } x11_display = display_device; display_device = ""; } else if (strncmp (_PATH_DEV, display_device, 5) != 0) { int len = strlen (_PATH_DEV) + strlen (display_device) + 1; ttybuf = malloc (len); if (ttybuf == NULL) { ck_pam_syslog (pamh, LOG_ERR, "oom allocating ttybuf"); goto out; } snprintf (ttybuf, len, _PATH_DEV "%s", display_device); display_device = ttybuf; } remote_host_name = NULL; s = NULL; res = pam_get_item (pamh, PAM_RHOST, (const void **) &s); if (res == PAM_SUCCESS && s != NULL && s[0] != '\0') { remote_host_name = s; if (opt_debug) { ck_pam_syslog (pamh, LOG_INFO, "using '%s' as remote-host-name", remote_host_name); } is_local = FALSE; } if ((s = pam_getenv (pamh, "CKCON_TTY")) != NULL) { display_device = s; if (opt_debug) { ck_pam_syslog (pamh, LOG_INFO, "using '%s' as display-device (from CKCON_TTY)", display_device); } } if ((s = pam_getenv (pamh, "CKCON_X11_DISPLAY")) != NULL) { x11_display = s; if (opt_debug) { ck_pam_syslog (pamh, LOG_INFO, "using '%s' as X11 display (from CKCON_X11_DISPLAY)", x11_display); } } x11_display_device = NULL; if ((s = pam_getenv (pamh, "CKCON_X11_DISPLAY_DEVICE")) != NULL) { x11_display_device = s; if (opt_debug) { ck_pam_syslog (pamh, LOG_INFO, "using '%s' as X11 display device (from CKCON_X11_DISPLAY_DEVICE)", x11_display_device); } } else if ((s = pam_getenv (pamh, "XDG_VTNR")) != NULL) { int len = strlen (s) + 10; /* room for "/dev/ttyXX\0" */ xdd = malloc (len); snprintf (xdd, len, "/dev/tty%s", s); x11_display_device = xdd; if (opt_debug) { ck_pam_syslog (pamh, LOG_INFO, "using '%s' as X11 display device (from XDG_VTNR)", x11_display_device); } } uid = _util_name_to_uid (user, NULL); if (uid == (uid_t) -1) { ck_pam_syslog (pamh, LOG_ERR, "cannot determine uid for user '%s'", user); goto out; } else { if (opt_debug) { ck_pam_syslog (pamh, LOG_INFO, "using %d as uid", uid); } } /* make sure no values are NULL */ if (x11_display == NULL) { x11_display = ""; } if (x11_display_device == NULL) { x11_display_device = ""; } if (remote_host_name == NULL) { remote_host_name = ""; } dbus_error_init (&error); res = ck_connector_open_session_with_parameters (ckc, &error, "unix-user", &uid, "display-device", &display_device, "x11-display", &x11_display, "x11-display-device", &x11_display_device, "remote-host-name", &remote_host_name, "is-local", &is_local, NULL); if (opt_debug) { ck_pam_syslog (pamh, LOG_INFO, "open session result: %d", res); } if (! res) { /* this might not be a bug for servers that don't have * the message bus or ConsoleKit daemon running - so * only log a message in debugging mode. */ if (dbus_error_is_set (&error)) { if (opt_debug) { ck_pam_syslog (pamh, LOG_DEBUG, "%s", error.message); } dbus_error_free (&error); } else { if (opt_debug) { ck_pam_syslog (pamh, LOG_DEBUG, "insufficient privileges or D-Bus / ConsoleKit not available"); } } goto out; } /* now set the cookie */ buf[sizeof (buf) - 1] = '\0'; snprintf (buf, sizeof (buf) - 1, "XDG_SESSION_COOKIE=%s", ck_connector_get_cookie (ckc)); if (pam_putenv (pamh, buf) != PAM_SUCCESS) { ck_pam_syslog (pamh, LOG_ERR, "unable to set XDG_SESSION_COOKIE in environment"); /* tear down session the hard way */ ck_connector_unref (ckc); ckc = NULL; goto out; } /* and set the runtime dir */ buf[sizeof (buf) - 1] = '\0'; runtime_dir = ck_connector_get_runtime_dir (ckc, &error); if (runtime_dir != NULL) { snprintf (buf, sizeof (buf) - 1, "XDG_RUNTIME_DIR=%s", runtime_dir); if (pam_putenv (pamh, buf) != PAM_SUCCESS) { ck_pam_syslog (pamh, LOG_ERR, "unable to set XDG_RUNTIME_DIR in environment"); /* tear down session the hard way */ ck_connector_unref (ckc); ckc = NULL; goto out; } } if (opt_debug) { ck_pam_syslog (pamh, LOG_DEBUG, "registered uid=%d on tty='%s' with ConsoleKit", uid, display_device); } /* note that we're leaking our CkConnector instance ckc - this * is *by design* such that when the login manager (that uses * us) exits / crashes / etc. ConsoleKit will notice, via D-Bus * connection tracking, that the login session ended. */ ret = PAM_SUCCESS; out: free (ttybuf); free (xdd); return ret; } #ifdef PAM_STATIC struct pam_module _pam_ckconnector_modstruct = { "pam_ck_connector", pam_sm_authenticate, pam_sm_setcred, NULL, pam_sm_open_session, pam_sm_close_session, NULL, }; #endif /* end of module definition */ consolekit2-1.2.6/pam-ck-connector/pam_ck_connector.8000066400000000000000000000041431446640754400225310ustar00rootroot00000000000000.\" Title: pam_ck_connector .\" Author: David Zeuthen .\" Date: 02/27/2007 .\" .TH "PAM_CK_CONNECTOR" "8" "02/27/2007" "ConsoleKit Manual" "ConsoleKit Manual" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .SH "NAME" pam_ck_connector \- Register session with ConsoleKit .SH "SYNOPSIS" .HP 12 \fBpam_ck_connector.so\fR [debug] .SH "DESCRIPTION" .PP The pam_ck_connector PAM module registers a login session with the system-wide .I ConsoleKit daemon. This PAM module should be used with caution; only local login managers such as .B login(1) should use this. Since the .I ConsoleKit daemon can accept both an .B tty and an X11 display the normal parameters set by PAM are not always useful. An application can therefore override these with the PAM environment variables .B CKCON_TTY, .B CKCON_X11_DISPLAY and .B CKCON_X11_DISPLAY_DEVICE (the application should remember to unset these before starting the login session). Also note that the .I ConsoleKit daemon may reject registration attempts if the given set of data are inconsistent with each other. More more information, see the .I ConsoleKit documentation on the .B OpenSessionWithParameters() method call on the .B org.freedesktop.ConsoleKit.Manager D-Bus interface. If registration with the .I ConsoleKit daemon succeeds, this PAM module will set the environment variable .B XDG_SESSION_COOKIE which is used to defined membership of a login session. This PAM module has the side effect that it creates a connection to the system message bus that is kept open until the session ends. This is used by the .I ConsoleKit daemon to track the life-cycle of the session and, as such, should the login manager crash, the session will be properly unregistered. .SH "OPTIONS" .PP .TP 3n \fBdebug\fR Print debug information. .TP 3n \fBnox11\fR Do not create a session if PAM specifies an X11 display instead of a /dev/tty terminal. .fi .RE .sp .SH "SEE ALSO" .PP \fBpam.conf\fR(5), \fBpam.d\fR(8), \fBpam\fR(8), \fBdbus-daemon\fR(1) .SH "AUTHOR" .PP pam_ck_connector was written by David Zeuthen . consolekit2-1.2.6/pam-ck-connector/test-pam.c000066400000000000000000000105251446640754400210330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2007 William Jon McCann * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include "config.h" #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif /* HAVE_PATHS_H */ #define PAM_MAX_LOGIN_TRIES 3 #define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ fprintf (stderr, "\n%s\n", pam_strerror (pamh, retcode)); \ pam_end (pamh, retcode); exit (1); \ } #define PAM_END { \ pam_setcred (pamh, PAM_DELETE_CRED); \ retcode = pam_close_session (pamh, 0); \ pam_end (pamh, retcode); \ } int main (int argc, char *argv[]) { int retcode; int ret; pam_handle_t *pamh; char *username; char *hostname; char *tty_name; char *ttyn; struct pam_conv conv = { misc_conv, NULL }; int failcount; ret = 1; username = NULL; hostname = NULL; tty_name = NULL; retcode = pam_start ("login", username, &conv, &pamh); if (retcode != PAM_SUCCESS) { fprintf (stderr, "login: PAM Failure, aborting: %s\n", pam_strerror (pamh, retcode)); exit (99); } ttyn = ttyname (0); if (strncmp (ttyn, _PATH_DEV, 5) == 0) { tty_name = ttyn + 5; } else { tty_name = ttyn; } retcode = pam_set_item (pamh, PAM_RHOST, hostname); PAM_FAIL_CHECK; retcode = pam_set_item (pamh, PAM_TTY, tty_name); PAM_FAIL_CHECK; pam_set_item (pamh, PAM_USER, NULL); retcode = pam_set_item (pamh, PAM_USER_PROMPT, "Username: "); PAM_FAIL_CHECK; failcount = 0; retcode = pam_authenticate (pamh, 0); while ((failcount++ < PAM_MAX_LOGIN_TRIES) && ((retcode == PAM_AUTH_ERR) || (retcode == PAM_USER_UNKNOWN) || (retcode == PAM_CRED_INSUFFICIENT) || (retcode == PAM_AUTHINFO_UNAVAIL))) { pam_get_item (pamh, PAM_USER, (const void **) &username); fprintf (stderr, "Login incorrect\n\n"); pam_set_item (pamh, PAM_USER, NULL); retcode = pam_authenticate (pamh, 0); } if (retcode != PAM_SUCCESS) { fprintf (stderr, "\nLogin incorrect\n"); pam_end (pamh, retcode); exit (0); } retcode = pam_acct_mgmt (pamh, 0); if (retcode == PAM_NEW_AUTHTOK_REQD) { retcode = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK); } PAM_FAIL_CHECK; pam_putenv (pamh, "CKCON_TTY=/dev/tty55"); pam_putenv (pamh, "CKCON_X11_DISPLAY=:50"); retcode = pam_open_session (pamh, 0); PAM_FAIL_CHECK; retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED); PAM_FAIL_CHECK; pam_get_item (pamh, PAM_USER, (const void **) &username); printf ("Session opened for %s\n", username); printf ("sleeping for 20 seconds..."); sleep (20); PAM_END; printf ("\nSession closed\n"); return ret; } consolekit2-1.2.6/po/000077500000000000000000000000001446640754400144105ustar00rootroot00000000000000consolekit2-1.2.6/po/ConsoleKit2.pot000066400000000000000000000207221446640754400172730ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: ConsoleKit2 1.2.2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-12-13 15:40+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "" #: src/main.c:230 msgid "Enable debugging code" msgstr "" #: src/main.c:231 msgid "Don't become a daemon" msgstr "" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "" #: src/main.c:261 msgid "Console kit daemon" msgstr "" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "" #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the " "error was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "" #: tools/ck-history.c:908 msgid "SEAT" msgstr "" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "" #: tools/ck-history.c:909 msgid "TYPE" msgstr "" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "" #: tools/ck-history.c:910 msgid "NAME" msgstr "" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "" consolekit2-1.2.6/po/LINGUAS000066400000000000000000000000611446640754400154320ustar00rootroot00000000000000# Set of available languages. bg es es_419 ru fr consolekit2-1.2.6/po/Makefile.in.in000066400000000000000000000415531446640754400170720ustar00rootroot00000000000000# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. # # Origin: gettext-0.19 GETTEXT_MACRO_VERSION = 0.19 PACKAGE = @PACKAGE@ VERSION = @VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ SED = @SED@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ localedir = @localedir@ gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ # We use $(mkdir_p). # In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as # "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, # @install_sh@ does not start with $(SHELL), so we add it. # In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined # either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake # versions, $(mkinstalldirs) and $(install_sh) are unused. mkinstalldirs = $(SHELL) @install_sh@ -d install_sh = $(SHELL) @install_sh@ MKDIR_P = @MKDIR_P@ mkdir_p = @mkdir_p@ GMSGFMT_ = @GMSGFMT@ GMSGFMT_no = @GMSGFMT@ GMSGFMT_yes = @GMSGFMT_015@ GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) MSGFMT_ = @MSGFMT@ MSGFMT_no = @MSGFMT@ MSGFMT_yes = @MSGFMT_015@ MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) XGETTEXT_ = @XGETTEXT@ XGETTEXT_no = @XGETTEXT@ XGETTEXT_yes = @XGETTEXT_015@ XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) MSGMERGE = msgmerge MSGMERGE_UPDATE = @MSGMERGE@ --update MSGINIT = msginit MSGCONV = msgconv MSGFILTER = msgfilter POFILES = @POFILES@ GMOFILES = @GMOFILES@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in remove-potcdate.sin \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ $(POFILES) $(GMOFILES) \ $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) POTFILES = \ CATALOGS = @CATALOGS@ POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot POFILESDEPS_yes = $(POFILESDEPS_) POFILESDEPS_no = POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT)) DISTFILESDEPS_ = update-po DISTFILESDEPS_yes = $(DISTFILESDEPS_) DISTFILESDEPS_no = DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO)) # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: .SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: all-@USE_NLS@ all-yes: stamp-po all-no: # Ensure that the gettext macros and this Makefile.in.in are in sync. CHECK_MACRO_VERSION = \ test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ exit 1; \ } # $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no # internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because # we don't want to bother translators with empty POT files). We assume that # LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. # In this case, stamp-po is a nop (i.e. a phony target). # stamp-po is a timestamp denoting the last time at which the CATALOGS have # been loosely updated. Its purpose is that when a developer or translator # checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, # "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent # invocations of "make" will do nothing. This timestamp would not be necessary # if updating the $(CATALOGS) would always touch them; however, the rule for # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot @$(CHECK_MACRO_VERSION) test ! -f $(srcdir)/$(DOMAIN).pot || \ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @test ! -f $(srcdir)/$(DOMAIN).pot || { \ echo "touch stamp-po" && \ echo timestamp > stamp-poT && \ mv stamp-poT stamp-po; \ } # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. # This target rebuilds $(DOMAIN).pot; it is an expensive operation. # Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. # The determination of whether the package xyz is a GNU one is based on the # heuristic whether some file in the top level directory mentions "GNU xyz". # If GNU 'find' is available, we avoid grepping through monster files. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed package_gnu="$(PACKAGE_GNU)"; \ test -n "$$package_gnu" || { \ if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f \ -size -10000000c -exec grep 'GNU @PACKAGE@' \ /dev/null '{}' ';' 2>/dev/null; \ else \ LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ fi; \ } | grep -v 'libtool:' >/dev/null; then \ package_gnu=yes; \ else \ package_gnu=no; \ fi; \ }; \ if test "$$package_gnu" = "yes"; then \ package_prefix='GNU '; \ else \ package_prefix=''; \ fi; \ if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ else \ msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ fi; \ case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ --msgid-bugs-address="$$msgid_bugs_address" \ ;; \ *) \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ --package-name="$${package_prefix}@PACKAGE@" \ --package-version='@VERSION@' \ --msgid-bugs-address="$$msgid_bugs_address" \ ;; \ esac test ! -f $(DOMAIN).po || { \ if test -f $(srcdir)/$(DOMAIN).pot; then \ sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ else \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ else \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ } # This rule has no dependencies: we don't need to update $(DOMAIN).pot at # every "make" invocation, only create it when it is missing. # Only "make $(DOMAIN).pot-update" or "make dist" will force an update. $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update # This target rebuilds a PO file if $(DOMAIN).pot has changed. # Note that a PO file is not touched if it doesn't need to be changed. $(POFILES): $(POFILESDEPS) @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ if test -f "$(srcdir)/$${lang}.po"; then \ test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) \ && { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ esac; \ }; \ else \ $(MAKE) $${lang}.po-create; \ fi install: install-exec install-data install-exec: install-data: install-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ for file in $(DISTFILES.common) Makevars.template; do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ for file in Makevars; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-data-no: all install-data-yes: all @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done install-strip: install installdirs: installdirs-exec installdirs-data installdirs-exec: installdirs-data: installdirs-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ fi; \ done; \ done # Define this as empty until I found a useful application. installcheck: uninstall: uninstall-exec uninstall-data uninstall-exec: uninstall-data: uninstall-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ for file in $(DISTFILES.common) Makevars.template; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi uninstall-data-no: uninstall-data-yes: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done check: all info dvi ps pdf html tags TAGS ctags CTAGS ID: mostlyclean: rm -f remove-potcdate.sed rm -f stamp-poT rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f stamp-po $(GMOFILES) distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS) @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: stamp-po $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ dists="$$dists $(DOMAIN).pot stamp-po"; \ fi; \ if test -f $(srcdir)/ChangeLog; then \ dists="$$dists ChangeLog"; \ fi; \ for i in 0 1 2 3 4 5 6 7 8 9; do \ if test -f $(srcdir)/ChangeLog.$$i; then \ dists="$$dists ChangeLog.$$i"; \ fi; \ done; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir) || exit 1; \ else \ cp -p $(srcdir)/$$file $(distdir) || exit 1; \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for creating PO files. .nop.po-create: @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ exit 1 # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ *) \ $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ esac; \ }; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: # Recreate Makefile by invoking config.status. Explicitly invoke the shell, # because execution permission bits may not work on the current file system. # Use @SHELL@, which is the shell determined by autoconf for the use by its # scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && @SHELL@ ./config.status $(subdir)/$@.in po-directories force: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: consolekit2-1.2.6/po/Makevars000066400000000000000000000062221446640754400161060ustar00rootroot00000000000000# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = The ConsoleKit2 Team # This tells whether or not to prepend "GNU " prefix to the package # name that gets inserted into the header of the $(DOMAIN).pot file. # Possible values are "yes", "no", or empty. If it is empty, try to # detect it automatically by scanning the files in $(top_srcdir) for # "GNU packagename" string. PACKAGE_GNU = # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = https://github.com/ConsoleKit2/ConsoleKit2/issues # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = # This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' # context. Possible values are "yes" and "no". Set this to yes if the # package uses functions taking also a message context, like pgettext(), or # if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. USE_MSGCTXT = no # These options get passed to msgmerge. # Useful options are in particular: # --previous to keep previous msgids of translated messages, # --quiet to reduce the verbosity. MSGMERGE_OPTIONS = # This tells whether or not to regenerate a PO file when $(DOMAIN).pot # has changed. Possible values are "yes" and "no". Set this to no if # the POT file is checked in the repository and the version control # program ignores timestamps. PO_DEPENDS_ON_POT = yes # This tells whether or not to forcibly update $(DOMAIN).pot and # regenerate PO files on "make dist". Possible values are "yes" and # "no". Set this to no if the POT file and PO files are maintained # externally. DIST_DEPENDS_ON_UPDATE_PO = yes consolekit2-1.2.6/po/POTFILES.in000066400000000000000000000021331446640754400161640ustar00rootroot00000000000000# List of source files containing translatable strings. src/ck-sysdeps-solaris.c src/ck-seat.h src/ck-sysdeps-linux.c src/ck-seat.c src/main.c src/ck-log-event.c src/ck-run-programs.h src/ck-job.c src/ck-vt-monitor.h src/ck-sysdeps-unix.c src/ck-marshal.c src/ck-session.h src/ck-manager.h src/ck-tty-idle-monitor.h src/ck-event-logger.c src/ck-sysdeps.h src/ck-event-logger.h src/ck-tty-idle-monitor.c src/ck-session-leader.c src/ck-log-event.h src/test-event-logger.c src/ck-log.c src/ck-run-programs.c src/ck-vt-monitor.c src/ck-file-monitor-dummy.c src/ck-file-monitor.h src/ck-file-monitor-inotify.c src/ck-sysdeps-gnu.c src/ck-manager.c src/ck-log.h src/ck-session-leader.h src/ck-session.c src/test-vt-monitor.c src/ck-marshal.h src/test-tty-idle-monitor.c src/ck-sysdeps-openbsd.c src/ck-job.h src/ck-sysdeps-freebsd.c src/ck-process-group.c tools/ck-history.c tools/list-sessions.c tools/ck-log-system-stop.c tools/ck-log-system-restart.c tools/ck-log-system-start.c tools/ck-get-x11-server-pid.c tools/udev-acl.c tools/ck-launch-session.c tools/ck-get-x11-display-device.c tools/ck-collect-session-info.c consolekit2-1.2.6/po/bg.po000066400000000000000000000321041446640754400153400ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # # Translators: # Ivailo Monev , 2015-2016 msgid "" msgstr "" "Project-Id-Version: ConsoleKit2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-12-13 15:40+0300\n" "PO-Revision-Date: 2017-09-22 11:45+0000\n" "Last-Translator: Eric Koegel \n" "Language-Team: Bulgarian (http://www.transifex.com/consolekit2/consolekit2/" "language/bg/)\n" "Language: bg\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "Š”Ń€ŃƒŠ³Š° ŃŠµŃŠøŃ беше активиранa Гокато се Ń‡Š°ŠŗŠ°ŃˆŠµ" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "ŠŃŠ¼Š° ДеГалка за активиране" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "ŠŠŗŃ‚ŠøŠ²Š°Ń†ŠøŃŃ‚Š° не се ŠæŠ¾Š“Š“ŃŠŃ€Š¶Š° за този тип сеГалка" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "ŠŠµŠæŠ¾Š·Š½Š°Ń‚Š¾ id на ŃŠµŃŠøŃŃ‚Š°" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "ŠŠµŠ²ŃŠŠ·Š¼Š¾Š¶Š½Š¾ активиране на ŃŠµŃŠøŃŃ‚Š°" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "Š”ŠµŃŠøŃŃ‚Š° не е прикачена към тази сеГалка" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "ДеГалката Š½ŃŠ¼Š° сесии" #: src/main.c:230 msgid "Enable debugging code" msgstr "Š’ŠŗŠ»ŃŽŃ‡Šø коГ за Гебъгване" #: src/main.c:231 msgid "Don't become a daemon" msgstr "ŠŠµ Гаемонизирай" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "Излез слеГ време - за Гебъгване" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "Š¢Ń€ŃŠ±Š²Š° Га сте root за Га ŠæŃƒŃŠ½ŠµŃ‚е тази програма" #: src/main.c:261 msgid "Console kit daemon" msgstr "Console kit Гаемон" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "Š”ŠµŃŠøŃŃ‚Š° вече е активна" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "ŠŃŠ¼Š° налични конзоли" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "ŠŠµ е ŠŃƒŃ‚оризиран: %s" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "ŠŃƒŠ¶Š½Š° е Š°ŃƒŃ‚Š¾Ń€ŠøŠ·Š°Ń†ŠøŃ" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "ŠŠµ е ŠŃƒŃ‚оризиран" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "ŠŠµŠ²ŃŠŠ·Š¼Š¾Š¶Š½Š¾ %s на системата: %s" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "ŠžŠæŠøŃ‚ за изпълнение на системно Гействие Гокато Š“Ń€ŃƒŠ³Š¾ е в прогрес" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "невъзможно алокиране на памет за ŠøŠ·ŠæŃŠŠ»Š½ŃŠ²Š°Š½ŠµŃ‚о на рестарт" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "ŠžŠæŠµŃ€Š°Ń†ŠøŃŃ‚Š° се Š·Š°Š“ŃŠŃ€Š¶Š°" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "невъзможно алокиране на памет за ŠøŠ·ŠæŃŠŠ»Š½ŃŠ²Š°Š½ŠµŃ‚о на ŠøŠ·ŠŗŠ»ŃŽŃ‡Š²Š°Š½Šµ" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "невъзможно алокиране на памет за ŠøŠ·ŠæŃŠŠ»Š½ŃŠ²Š°Š½ŠµŃ‚о на заспиване" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "невъзможно алокиране на памет за ŠøŠ·ŠæŃŠŠ»Š½ŃŠ²Š°Š½ŠµŃ‚о на Ń…ŠøŠ±ŠµŃ€Š½Š°Ń†ŠøŃ" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "невъзможно алокиране на памет за ŠøŠ·ŠæŃŠŠ»Š½ŃŠ²Š°Š½ŠµŃ‚о на хибриГно заспиване" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "Š“Ń€ŠµŃˆŠŗŠ° при съзГаване ŠŗŠ»ŃŽŃ‡ŃŠ за Š·Š°Š“ŃŠŃ€Š¶Š°Š½Šµ" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "Š—Š°Š“ŃŠŃ€Š¶Š°Ń‰ŠøŃŃ‚ Š¼ŠµŠ½ŠøŠ“Š¶ŃŠŃ€ не ŃƒŃŠæŃ Га се инициализира" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "ŠŠµŠ²Š°Š»ŠøŠ“ŠµŠ½ вхоГ при съзГаване на ŠŗŠ»ŃŽŃ‡ за ŠøŠ½Ń…ŠøŠ±Š°Ń†ŠøŃ" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "ŠŠµŠ²ŃŠŠ·Š¼Š¾Š¶Š½Š¾ ŃŃŠŠ·Š“Š°Š²Š°Š½ŠµŃ‚Š¾ на Š·Š°Š“ŃŠŃ€Š¶Š°Ń‰ ŠŗŠ»ŃŽŃ‡, Š½ŠµŠ“Š¾ŃŃ‚Š°Ń‚ŃŠŃ‡Š½Š¾ памет" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "Š’ момента Š½ŃŠ¼Š° нищо за Š·Š°Š“ŃŠŃ€Š¶Š°Š½Šµ" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "ŠŠµŠ²ŃŠŠ·Š¼Š¾Š¶Š½Š¾ извличане на ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃ за ŠøŠ·Š²ŠøŠŗŠ²Š°Ń‰ŠøŃŃ‚ процес" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "ŠŠµŠ²ŃŠŠ·Š¼Š¾Š¶Š½Š¾ намиране на ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃ за ŠøŠ·Š²ŠøŠŗŠ²Š°Ń‰ŠøŃŃ‚ процес '%d'" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "ŠŠµŠ²ŃŠŠ·Š¼Š¾Š¶Š½Š¾ намиране на ŃŠµŃŠøŃ за бизквитка" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "pid Ń‚Ń€ŃŠ±Š²Š° Га е > 1" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "ŠŠµŠ²ŃŠŠ·Š¼Š¾Š¶Š½Š¾ намиране на сесиина ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃ за процес '%d'" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "ŠŸŠ¾Ń‚Ń€ŠµŠ±ŠøŠ»ŃŠŗŠ¾Ń‚Š¾ ID несъвпаГа с това на ŠæŃ€ŠøŃ‚ŠµŠ¶Š°Ń‚ŠµŠ»Ń на бизквитката" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "ŠŸŃ€Š¾Ń†ŠµŃŠ½Š¾Ń‚Š¾ ID несъвпаГа с това на ŠæŃ€ŠøŃ‚ŠµŠ¶Š°Ń‚ŠµŠ»Ń на бизквитката" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "ŠŸŠ¾Ń‚Ń€ŠµŠ±ŠøŃ‚ŠµŠ»Ń Š½ŃŠ¼Š° сесии" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "ŠŸŠ¾Ń‚Ń€ŠµŠ±ŠøŃ‚ŠµŠ»Ń Š½ŃŠ¼Š° сеГалки" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "ŠŃŠ¼Š° сесии" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "Дамо ŃŠµŃŠøŠøŠ½ŠøŃŃ‚ воГач може Га заГаГе поГсказка за ŃŃ‚Š°Ń‚ŃƒŃ" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "" "Дигнал за активиране не е обработен. Š”ŠµŃŠøŃ не е прикачена към сеГалка, или " "сеГалката не ŠæŠ¾Š“Š“ŃŠŃ€Š¶Š° промени на Š°ŠŗŃ‚ŠøŠ²Š°Ń†ŠøŃŃ‚Š°" #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "Š“Ń€ŠµŃˆŠŗŠ° при ŃŃŠŠ·Š“Š°Š²Š°Š½ŠµŃ‚Š¾ на XDG_RUNTIME_DIR" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "" "ŠŠµŃƒŃŠæŠµŃ… при Š¾Ń‚Š²Š°Ń€ŃŠ½ŠµŃ‚Š¾ на Š²Ń€ŃŠŠ·ŠŗŠ° към cgmanager. cgmanager Š“ŠµŠ¼Š¾Š½ŃŠŃ‚ ŠæŃƒŃŠ½Š°Ń‚ ли " "е?" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "Š’ŃŠŠ·Š½ŠøŠŗŠ½Š° Š³Ń€ŠµŃˆŠŗŠ° при инициализирането на cgmanager, Š³Ń€ŠµŃˆŠŗŠ°Ń‚Š° беше: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "ŠŠµŃƒŃŠæŠµŃ… при ŃŃŠŠ·Š“Š°Š²Š°Š½ŠµŃ‚Š¾ на cgroup, Š³Ń€ŠµŃˆŠŗŠ°Ń‚Š° беше: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the " "error was: %s" msgstr "" "ŠŠµŃƒŃŠæŠµŃ… при ŠæŃ€Š¾Š¼ŃŠ½Š° ŠæŃ€ŠøŃ‚ŠµŠ¶Š°Ń‚ŠµŠ»Ń на нова cgroup към притежател на ŃŠµŃŠøŠ¹Š½ŠøŃŃ‚ " "воГач, Š³Ń€ŠµŃˆŠŗŠ°Ń‚Š° беше: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "Š“Ń€ŠµŃˆŠŗŠ° при опит за откриване на id от cgmanager, Š³Ń€ŠµŃˆŠŗŠ°Ń‚Š° беше: %s" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "Š’ŠµŃ€ŃŠøŃŃ‚Š° на това приложение" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "Покажи лист на чести потребители" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "Покажи лист на послеГно влезли потребители" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "Покажи 'послеГен' ŃŃŠŠ²Š¼ŠµŃŃ‚ŠøŠ¼ лист на послеГно Š²ŠŗŠ»ŃŽŃ‡ŠøŠ»ŠøŃ‚е се потребители" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "Покажи пълен лог на ŃŠ»ŃƒŃ‡ŠŗŠøŃ‚Šµ" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "Покажи Š²ŠŗŠ»ŃŽŃ‡Š²Š°Š½ŠøŃ за специфицираната сеГалка" #: tools/ck-history.c:908 msgid "SEAT" msgstr "Š”Š•Š”ŠŠ›ŠšŠ" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "Покажи Š²ŠŗŠ»ŃŽŃ‡Š²Š°Š½ŠøŃ за ŃŠæŠµŃ†ŠøŃ„ŠøŃ†ŠøŃ€Š°Š½ŠøŃŃ‚ тип ŃŠµŃŠøŃ" #: tools/ck-history.c:909 msgid "TYPE" msgstr "ТИП" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "Покажи Š²ŠŗŠ»ŃŽŃ‡Š²Š°Š½ŠøŃ за ŃŠæŠµŃ†ŠøŃ„ŠøŃ†ŠøŃ€Š°Š½ŠøŃŃ‚ потребител" #: tools/ck-history.c:910 msgid "NAME" msgstr "Š˜ŠœŠ•" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "Покажи Š²ŠŗŠ»ŃŽŃ‡Š²Š°Š½ŠøŃ от специфицираното време (ISO 8601 формат)" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "ДАТА" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "име на Гисплей" consolekit2-1.2.6/po/de.po000066400000000000000000000276411446640754400153520ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # # Translators: # kraileth , 2017 msgid "" msgstr "" "Project-Id-Version: ConsoleKit2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-11-09 04:42+0300\n" "PO-Revision-Date: 2017-10-11 17:17+0000\n" "Last-Translator: kraileth \n" "Language-Team: German (http://www.transifex.com/consolekit2/consolekit2/language/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "WƤhrend des Wartens wurde eine andere Sitzung aktiviert" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "Es gibt keinen aktivierbaren Seat" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "Für diese Art von Seat wird keine Aktivierung unterstützt" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "Unbekannte Sitzungs-ID" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "Kann Sitzung nicht aktivieren" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "Kann VT für den Seat nicht Ƥndern" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "Sitzung ist an diesen Seat nicht angeschlossen" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "Seat hat keine Sitzungen" #: src/main.c:230 msgid "Enable debugging code" msgstr "Debugging-Code einschalten" #: src/main.c:231 msgid "Don't become a daemon" msgstr "Nicht in den Daemon-Modus wechseln" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "Nach einer bestimmten Zeit beenden - zu Debugzwecken" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "Sie müssen Root sein, um dieses Programm auszuführen" #: src/main.c:261 msgid "Console kit daemon" msgstr "ConsoleKit-Daemon" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "Sitzung ist bereits aktiv" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "Keine Konsolen verfügbar" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "Nicht autorisiert: %s" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "Autorisierung benƶtigt" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "Nicht autorisiert" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "Kann nicht %s system: %s" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "Versuch, eine Systemaktion durchzuführen, wƤhrend eine andere lƤuft" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "Konnte keinen Speicher reservieren um einen Neustart durchzuführen" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "Operation wird blockiert" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "Konnte keinen Speicher reservieren um herunterzufahren" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "Konnte keinen Speicher reservieren um in den Bereitschaftszustand zu wechseln" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "Konnte keinen Speicher reservieren um in den Ruhezustand zu wechseln" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "Konnte keinen Speicher reservieren um in den Hybridschlafmodus zu wechseln" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "Fehler beim Erstellen der Sperre" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "Sperrungsmanager konnte nicht initialisiert werden" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "Ungültige Eingabe beim Erstellen der Sperre" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "Konnte Sperre nicht erstellen, nicht genügend Speicher" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "Zur Zeit wird nichts blockiert" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "Konnte keine Informationen über den aufrufenden Prozess bekommen" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "Kann keine Informationen über den aufrufenden Prozess ā€ž%dā€œ finden" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "Konnte keine Sitzung für das Cookie finden" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "PID muß > 1 sein" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "Kann keine Sitzungsinformationen für Prozess ā€ž%dā€œ finden" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "Benutzer-ID entspricht nicht dem Besitzer des Cookies" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "Prozess-ID entspricht nicht dem Besitzer des Cookies" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "Benutzer hat keine Sitzungen" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "Ungültige Sitzung" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "Ungültiger Seat" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "Sitzung ist an keinen Seat angeschlossen" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "Benutzer hat keine Seats" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "Es gibt keine Sitzungen" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "Nur der Besitzer der Sitzung darf den idle-hint-Status setzen" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "Nur der Besitzer der Sitzung darf den locked-hint-Status setzen" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "Aktives Signal wird nicht behandelt. Sitzung ist nicht an den Seat angeschlossen oder der Seat unterstützt keine AktivierungsƤnderungen" #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "Konnte das XDG_RUNTIME_DIR-Verzeichnis nicht erstellen" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "Server-verwaltete GerƤte werden nicht unterstützt" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "Konnte UID des dbus-Aufrufers nicht bekommen" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "Konnte den aktuellen Sitzungs-Controller nicht ersetzen" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "Sitzungs-Controller besteht bereits" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "Nur der Sitzungs-Controller darf diese Funktion nutzen" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "Nur der Sitzungs-Controller darf diese Funktion aufrufen" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "GerƤt wurde bereits angefordert" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "Konnte GerƤt nicht erstellen" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "Konnte Datei-Handle für das GerƤt nicht bekommen" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "GerƤt existiert nicht" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "Konnte keine Verbindung zum cgmanager herstellen. LƤuft der cgmanager-Daemon?" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "Ein Fehler trat beim Initialisieren des cgmanagers auf, der Fehler war: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "Konnte cgroup nicht erstellen, der Fehler war: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the" " error was: %s" msgstr "Konnte den Besitzer der neuen cgroup nicht zum Besitzer des Sitzungsleiters Ƥndern, der Fehler war: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "Konnte den Besitzungsleiterprozess nicht in die cgroup ā€žcpuacctā€œ verschieben, der Fehler war: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "Konnte die Sitzungs-ID nicht vom cgmanager bekommen, der Fehler war: %s" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "Version dieses Programms" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "Zeige Auflistung regelmäßiger Benutzer" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "Zeige Auflistung der zuletzt eingeloggten Benutzer" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "Zeige ā€žletzteā€œ kompatible Auflistung der zuletzt eingeloggten Benutzer" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "Zeige vollstƤndiges Ereignislog" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "Zeige EintrƤge für den angegebenen Seat" #: tools/ck-history.c:908 msgid "SEAT" msgstr "SEAT" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "Zeige EintrƤge für die angegebene Sitzungsart" #: tools/ck-history.c:909 msgid "TYPE" msgstr "ART" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "Zeige EintrƤge für den angegebenen Benutzer" #: tools/ck-history.c:910 msgid "NAME" msgstr "NAME" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "Zeige EintrƤge seit der angegebenen Zeit (im ISO-8601-Format)" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "DATUMZEIT" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "Anzeigename" consolekit2-1.2.6/po/es.po000066400000000000000000000303611446640754400153620ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # # Translators: # Joel Barrios , 2017 # Pablo Lezaeta Reyes [pˈaĪ²Ģžlo lˌeĢžĪøaˈeta rˈejɛ] , 2015 # Pablo Lezaeta Reyes [pˈaĪ²Ģžlo lˌeĢžĪøaˈeta rˈejɛ] , 2016 msgid "" msgstr "" "Project-Id-Version: ConsoleKit2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-12-13 15:40+0300\n" "PO-Revision-Date: 2017-10-14 23:06+0000\n" "Last-Translator: Joel Barrios \n" "Language-Team: Spanish (http://www.transifex.com/consolekit2/consolekit2/" "language/es/)\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "Otra sesión fue iniciada mientras se esperaba" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "No hay un puesto de trabajo activado" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "La activación no estĆ” soportada por este tipo de puesto de trabajo" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "Id de sesión desconocido" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "No se pudo activar la sesión" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "No se pudo cambiar VT para el asiento" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "La sesión no estĆ” adjunta a este puesto de trabajo" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "El puesto de trabajo no tiene una sesión" #: src/main.c:230 msgid "Enable debugging code" msgstr "Habilitar código de depuración" #: src/main.c:231 msgid "Don't become a daemon" msgstr "No convertirse en un servicio en segundo plano" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "Salir despuĆ©s de un tiempo - para depurar" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "Debe ser superusuario para ejecutar este programa" #: src/main.c:261 msgid "Console kit daemon" msgstr "Kit de servicio de consola" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "La sesión estĆ” activa" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "No hay consolas disponibles" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "No autorizado: %s" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "Se requiere una autorización" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "No autorizado" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "No se pudo %s al sistema: %s" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "Intentando realizar acción de sistema mientras hay otra en progreso" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "No se pudo reasignar memoria para realizar reinicio" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "Operación estĆ” siendo inhibida" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "No se pudo reasignar memoria para realizar apagado" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "No se pudo reasignar memoria para realizar suspensión" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "No se pudo reasignar memoria para realizar hibernación" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "No se pudo reasignar memoria para realizar suspensión hĆ­brida" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "Error al crear el bloqueo de inhibición" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "Gestor de inhibición falló al inicializar" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "Entrada invĆ”lida al crear bloqueo de inhibición" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "No se puede crear bloqueo de inhibición, memoria insuficiente" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "No hay nada siendo inhibido en este momento" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "No se puede buscar información acerca de las llamadas a proceso" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "No se puede buscar información acerca de la llamada al proceso Ā«%dĀ»" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "No se pudo encontrar la sesión para la cookie" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "el pid debe ser > 1" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "No se puede buscar información de la sesión para el proceso Ā«%dĀ»" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "El Id del usuario no concuerda con el propietario de la cookie" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "El id del proceso no concuerda con el propietario de la cookie" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "El usuario no tiene sesión" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "Sesión invĆ”lida" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "Asiento invĆ”lido" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "Sesión no estĆ” unida al asiento" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "El usuario no tiene puesto de trabajo" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "Sin sesiones" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "" "Solo el propietario de la sesión puede establecer el estado de toque de " "inactividad" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "" "Sólo el propietario de la sesión puede bloquear el estado de sugerencia" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "" "La seƱal de activación no se ha manejada. La sesión no se pudo unir al " "puesto de trabajo, o el puesto de trabajo no admite cambios de activación." #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "No se pudo crear XDG_RUNTIME_DIR" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "Dispositivos administrados por servidor no admitidos" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "Error al obtener uid de la llamada dbus" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "No se pudo reemplazar el controlador de sesión actual" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "Controlador de sesión ya estĆ” presente" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "Sólo el controlador de sesión puede utilizar esta función" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "Sólo el controlador de sesión puede invocar esta función" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "Dispositivo ya ha sido solicitado" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "No se pudo crear dispositivo" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "Error al obtener el descriptor de archivo para el dispositivo" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "Dispositivo inexistente" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "" "No se pudo abrir conexión hacia cgmanager. ĀæSe estĆ” ejecutando el servicio " "cgmanager?" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "Hubo un error al inicializar cgmanager, el error fue: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "No se pudo crear el cgroup, el error fue: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the " "error was: %s" msgstr "" "No se pudo cambiar el propietario del nuevo cgroup al propietario de la " "sesión lĆ­der, el error fue: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "" "No se pudo mover el proceso de la seisón lĆ­der al cgroup 'cpuacct', el error " "fue: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "No se pudo obtener el id de sesión de cgmanager, el error fue: %s" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "La versión de esta aplicación" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "Lista los usuario frecuentes" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "Muestra la lista de los Ćŗltimos usuarios conectados" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "" "Muestra la «últimaĀ» lista compatible de los Ćŗltimos usuarios conectados" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "Muestra el registro de eventos completo" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "Muestra las entradas especĆ­ficas por el puesto de trabajo" #: tools/ck-history.c:908 msgid "SEAT" msgstr "PUESTO DE TRABAJO" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "Mostrar las entradas especĆ­ficas para el tipo de sesión" #: tools/ck-history.c:909 msgid "TYPE" msgstr "TIPO" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "Muestra las entradas especĆ­ficas para el usuario" #: tools/ck-history.c:910 msgid "NAME" msgstr "NOMBRE" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "Muestra las entradas especĆ­ficas para la fecha (en formato ISO 8601)" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "FECHA Y HORA" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "Mostrar nombre" consolekit2-1.2.6/po/es_419.po000066400000000000000000000246621446640754400157660ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # # Translators: # Pablo Lezaeta Reyes [pˈaĪ²Ģžlo lˌeĢžĪøaˈeta rˈejɛ] , 2015 msgid "" msgstr "" "Project-Id-Version: ConsoleKit2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-12-13 15:40+0300\n" "PO-Revision-Date: 2017-09-21 23:25+0000\n" "Last-Translator: Eric Koegel \n" "Language-Team: Spanish (Latin America) (http://www.transifex.com/consolekit2/" "consolekit2/language/es_419/)\n" "Language: es_419\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "Se inició otra sesión mientras se estaba en espera" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "No hay puesto de trabajo activo" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "La activación no estĆ” disponible para este tipo de puesto de trabajo" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "El Id de sesión desconocido" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "No se pudo activar la sesión" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "La sesión no estĆ” adjunta a este puesto de trabajo" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "El puesto de trabajo no tiene sesiones" #: src/main.c:230 msgid "Enable debugging code" msgstr "Habilitar código de depuración" #: src/main.c:231 msgid "Don't become a daemon" msgstr "No convertirse en un demonio" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "Salir despuĆ©s de un tiempo - para depurar" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "Debe ser superusuario para ejecutar este programa" #: src/main.c:261 msgid "Console kit daemon" msgstr "Kit de demonio de consola" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "La sesión estĆ” activa" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "No hay consolas disponibles" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "No estĆ” autorizado: %s" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "Se requiere atorización" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "No estĆ” autorizado" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "No se puede %s al sistema: %s" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "No se puede buscar información acerca de las llamadas a proceso" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "No se puede buscar información acerca de las llamadas al proceso Ā«%dĀ»" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "No se pudo encontrar la sesión para la galleta" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "el pid debe ser > 1" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "No se puede buscar información de la sesión para el proceso Ā«%dĀ»" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "El Id del usuario no concuerda con el propietario de la galleta" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "El id del proceso no concuerda con el propietario de la cookie" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "El usuario estĆ” sin sesión" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "El usuario no tiene un puesto de trabajo" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "No hay sesiones" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "" "Solo el propietario de la sesión puede establecer el estado de de inactividad" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "" "No se pudo manejar la seƱal de activación. La sesión no se adjuntarĆ” al " "puesto de trabajo o el puesto no soporta cambios de activación" #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the " "error was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "La versión de esta aplicación" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "Lista los usuario frecuentes" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "Muestra la lista de los Ćŗltimos usuarios conectados" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "" "Muestra la «últimaĀ» lista compatible de los Ćŗltimos usuarios conectados" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "Muestra todo el registro de eventos" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "Muestra las entradas especĆ­ficas por el puesto de trabajo" #: tools/ck-history.c:908 msgid "SEAT" msgstr "PUESTO DE TRABAJO" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "Mostrar las entradas especĆ­ficas para el tipo de sesión" #: tools/ck-history.c:909 msgid "TYPE" msgstr "TIPO" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "Muestra las entradas especĆ­ficas para el usuario" #: tools/ck-history.c:910 msgid "NAME" msgstr "NOMBRE" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "Muestra las entradas especĆ­ficas para la fecha (en formato ISO 8601)" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "FECHA Y HORA" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "Mostrar nombre" consolekit2-1.2.6/po/fr.po000066400000000000000000000303211446640754400153560ustar00rootroot00000000000000# French translations for ConsoleKit2 package. # Copyright (C) 2020 The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # Jean Philippe EIMER , 2020. # msgid "" msgstr "" "Project-Id-Version: ConsoleKit2 1.2.2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-12-13 15:40+0300\n" "PO-Revision-Date: 2020-12-30 16:10+0100\n" "Last-Translator: Jean Philippe EIMER \n" "Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "Une autre session a Ć©tĆ© activĆ©e pendant l'attente" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "Il n'y a pas de poste (seat) Ć  activer" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "L'activation n'est pas supportĆ©e pour ce type de poste (seat)" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "Identifiant de session inconnu" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "Impossible d'activer la session" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "Impossible de changer de terminal virtuel pour le poste (seat)" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "La session n'est pas attachĆ©e Ć  ce poste (seat)" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "Le poste (seat) n'a pas de session" #: src/main.c:230 msgid "Enable debugging code" msgstr "Activation du code de dĆ©bogage" #: src/main.c:231 msgid "Don't become a daemon" msgstr "Ne s'exĆ©cute pas comme dĆ©mon" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "S'arrĆŖte aprĆØs un certain temps - pour dĆ©boguer" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "Vous devez ĆŖtre 'root' pour exĆ©cuter ce programme" #: src/main.c:261 msgid "Console kit daemon" msgstr "DĆ©mon ConsoleKit" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "La session est dĆ©jĆ  active" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "Aucune console n'est disponible" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "Non autorisĆ© : %s" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "Une autorisation est nĆ©cessaire" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "Non autorisĆ©" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "Impossible de %s le systĆØme : %s" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "Tentative de rĆ©aliser une action systĆØme alors qu'il y en a une en cours" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "Ć©chec d'allocation mĆ©moire pour rĆ©aliser un redĆ©marrage" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "L'opĆ©ration est inhibĆ©e" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "Ć©chec d'allocation mĆ©moire pour rĆ©aliser l'extinction" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "Ć©chec d'allocation mĆ©moire pour rĆ©aliser la mise en veille" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "Ć©chec d'allocation mĆ©moire pour rĆ©aliser l'hibernation" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "Ć©chec d'allocation mĆ©moire pour rĆ©aliser la veille hybride" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "Erreur en crĆ©ant le verrou d'inhibition" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "Le gestionnaire d'inhibition n'a pas pu s'initialiser" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "EntrĆ©e invalide lors de la crĆ©ation du verrou d'inhibition" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "Impossible de crĆ©er le verrou d'inhibition, mĆ©moire insuffisante" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "Il n'y a rien d'inhibĆ©" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "Impossible d'obtenir des informations sur le processus appelant" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "Impossible de rechercher des informations sur le processus appelant '%d'" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "Impossible de trouver une session pour le cookie" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "le PID doit ĆŖtre > 1" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "Impossible de rechercher des informations de session pour le processus '%d'" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "L'identifiant utilisateur ne correspond pas au propriĆ©taire du cookie" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "L'identifiant du processus ne correspond pas au propriĆ©taire du cookie" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "L'utilisateur n'a pas de session" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "Session invalide" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "Ticket invalide" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "La session n'est pas attachĆ©e Ć  un poste (seat)" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "L'utilisateur n'a pas de poste (seat)" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "Il n'y a pas de session" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "Seul le propriĆ©taire de la session peut modifier l'Ć©tat en 'attente'" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "Seul le propriĆ©taire de la session peut modifier l'Ć©tat en 'verrouillĆ©'" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "" "Signal d'activation non gĆ©rĆ©. La session n'est pas attachĆ©e Ć  un poste (seat), " "ou celui-ci ne supporte pas de modification d'activation" #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "Impossible de crĆ©er le rĆ©pertoire XDG_RUNTIME_DIR" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "Les pĆ©riphĆ©riques gĆ©rĆ©s par le serveur ne sont pas supportĆ©s" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "Impossible d'obtenir l'identifiant utilisateur du processus ayant lancĆ© DBus" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "Impossible de remplacer le contrĆ“leur de session en cours" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "Un contrĆ“leur de session est dĆ©jĆ  prĆ©sent" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "Seul le contrĆ“leur de session peut utiliser cette fonction" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "Seul le contrĆ“leur de session peut appeler cette fonction" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "Le pĆ©riphĆ©rique a dĆ©jĆ  Ć©tĆ© demandĆ©" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "Impossible de crĆ©er le pĆ©riphĆ©rique" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "Impossible d'obtenir un descripteur de fichier pour le pĆ©riphĆ©rique" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "Le pĆ©riphĆ©rique n'existe pas" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "Impossible d'ouvrir une connexion vers cgmanager. Est-il en cours d'exĆ©cution ?" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "Une erreur s'est produite Ć  l'initialisation de cgmanager : %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "Erreur lors de la crĆ©ation du cgroup : %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the " "error was: %s" msgstr "" "Erreur lors de l'affectation du responsable de session comme " "propriĆ©taire du nouveau cgroup : %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "" "Erreur lors du dĆ©placement du processus du responsable de session vers " "le cgroup 'cpuacct' : %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "Erreur pour obtenir un identifiant de session de la part de cgmanager : %s" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "Version de cette application" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "Lister les utilisateurs frĆ©quents" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "Lister les derniers utilisateurs connectĆ©s" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "Montrer la 'derniĆØre' liste compatible des derniers utilisateurs connectĆ©s" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "Afficher le journal d'Ć©vĆØnements complet" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "Montrer les Ć©lĆ©ments pour le poste (seat) spĆ©cifiĆ©" #: tools/ck-history.c:908 msgid "SEAT" msgstr "TICKET" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "Montrer les Ć©lĆ©ments pour le type de session spĆ©cifiĆ©" #: tools/ck-history.c:909 msgid "TYPE" msgstr "TYPE" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "Montrer les Ć©lĆ©ments pour l'utilisateur spĆ©cifiĆ©" #: tools/ck-history.c:910 msgid "NAME" msgstr "NOM" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "Montrer les Ć©lĆ©ments depuis l'instant spĆ©cifiĆ© (au format ISO 8601)" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "INSTANT" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "Nom du 'Display'" consolekit2-1.2.6/po/nl.po000066400000000000000000000274321446640754400153710ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # # Translators: # Eric Hameleers , 2015-2017 msgid "" msgstr "" "Project-Id-Version: ConsoleKit2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-11-09 04:42+0300\n" "PO-Revision-Date: 2017-09-22 16:44+0000\n" "Last-Translator: Eric Hameleers \n" "Language-Team: Dutch (http://www.transifex.com/consolekit2/consolekit2/language/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "Een andere sessie werd geactiveerd tijdens het wachten" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "Er is geen Seat om te activeren" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "Activeren wordt niet ondersteund voor dit type seat" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "Onbekend sessie id" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "Kan geen sessie activeren" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "Kan VT niet aanpassen voor seat" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "Sessie is niet gekoppeld aan deze seat" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "Seat heeft geen sessies" #: src/main.c:230 msgid "Enable debugging code" msgstr "Activeer code voor foutoplossing" #: src/main.c:231 msgid "Don't become a daemon" msgstr "Word geen achtergrondproces" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "Sluit pas af na zekere tijd - voor foutoplossing" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "Je moet root zijn om dit programma te starten" #: src/main.c:261 msgid "Console kit daemon" msgstr "Console kit achtergrondproces" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "Sessie is al actief" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "Geen consoles beschikbaar" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "Niet Geauthoriseerd: %s" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "Authorisatie is vereist" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "Niet Geauthoriseerd" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "Kan systeem niet %s: %s" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "Poging om een systeem actie uit te voeren terwijl er al een in uitvoering is" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "kon geen geheugen vrijmaken voor een herstart" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "Operatie wordt tegengehouden" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "kon geen geheugen vrijmaken om systeem te stoppen" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "kon geen geheugen vrijmaken om systeem te pauzeren" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "kon geen geheugen vrijmaken om systeem in slaapstand te zetten" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "kon geen geheugen vrijmaken om systeem in hybride slaapstand te zetten" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "Fout bij het aanmaken van het inhibit lock" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "Inhibit manager kon niet worden geĆÆnitialiseerd" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "Ongeldige invoer bij het aanmaken van het inhibit lock" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "Kon geen inhibit lock aanmaken, onvoldoende geheugen" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "Momenteel worden er geen operaties tegengehouden" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "Kan geen informatie krijgen over het aanroepende proces" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "Kan geen informatie opzoeken over aanroepende proces '%d'" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "Kan geen sessie vinden bij het cookie" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "PID moet > 1 zijn" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "Kan geen sessie informatie opzoeken voor proces '%d'" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "Gebruikers ID klopt niet met de eigenaar van het cookie" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "Proces ID klopt niet met de eigenaar van het cookie" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "Gebruiker heeft geen sessies" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "Ongeldige sessie" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "Ongeldige seat" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "Sessie is niet gekoppeld aan een seat" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "Gebruiker heeft geen seats" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "Er zijn geen sessies" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "Enkel de sessie eigenaar mag de idle hint status zetten" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "Enkel de sessie eigenaar mag de locked hint status zetten" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "Signaal activatie niet afgehandeld. Sessie niet gekoppeld aan seat, of de seat ondersteunt geen activatie wijziging" #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "Kon XDG_RUNTIME_DIR niet aanmaken" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "Door server beheerde apparaten worden niet ondersteund" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "Kon uid niet vinden van dbus caller" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "Kon de huidige sessie controller niet vervangen" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "Sessie controller bestaat al" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "Alleen de sessie controller mag deze functie gebruiken" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "Alleen de sessie controller mag deze functie aanroepen" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "Apparaat is reeds aangevraagd" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "Kon apparaat niet aanmaken" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "Kon geen bestandindicator verkrijgen voor apparaat" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "Apparaat bestaat niet" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "Kon geen verbinding maken met cgmanager. Is het cgmanager achtergrondproces actief?" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "Er trad een fout op bij het initialiseren van cgmanager, de melding was: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "Kon geen cgroup aanmaken, de foutmelding was: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the" " error was: %s" msgstr "Kon de eigenaar van de nieuwe cgroup niet veranderen naar de eigenaar van het session leader proces, de foutmelding was: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "Kon het session leader proces niet naar 'cpuacct' cgroup verplaatsen, de foutmelding was: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "Kon de sessie id niet verkrijgen van cgmanager, de foutmelding was: %s" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "Versie van deze applicatie" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "Toon overzicht van frequente gebruikers" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "Toon overzicht van recent ingelogde gebruikers" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "Toon overzicht van recent ingelogde gebruikers dat compatibel is met het 'last' commando" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "Toon volledig logboek van gebeurtenissen" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "Toon logboekvermeldingen van de genoemde seat" #: tools/ck-history.c:908 msgid "SEAT" msgstr "SEAT" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "Toon vermeldingen van het genoemde sessie type" #: tools/ck-history.c:909 msgid "TYPE" msgstr "TYPE" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "Toon vermeldingen van de genoemde gebruiker" #: tools/ck-history.c:910 msgid "NAME" msgstr "NAAM" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "Toon vermeldingen vanaf het genoemde tijdstip (ISO 8601 formaat)" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "DAGTIJD" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "schermnaam" consolekit2-1.2.6/po/ru.po000066400000000000000000000342161446640754400154040ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR The ConsoleKit2 Team # This file is distributed under the same license as the ConsoleKit2 package. # # Translators: # Дмитрий ŠœŠøŃ…ирев, 2015-2016 # Дмитрий ŠœŠøŃ…ирев, 2017 msgid "" msgstr "" "Project-Id-Version: ConsoleKit2\n" "Report-Msgid-Bugs-To: https://github.com/ConsoleKit2/ConsoleKit2/issues\n" "POT-Creation-Date: 2017-12-13 15:40+0300\n" "PO-Revision-Date: 2017-09-22 00:17+0000\n" "Last-Translator: Дмитрий ŠœŠøŃ…ирев\n" "Language-Team: Russian (http://www.transifex.com/consolekit2/consolekit2/" "language/ru/)\n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" "%100>=11 && n%100<=14)? 2 : 3);\n" #: src/ck-seat.c:253 msgid "Another session was activated while waiting" msgstr "За Š²Ń€ŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ была активирована Š“Ń€ŃƒŠ³Š°Ń ŃŠµŃŃŠøŃ" #: src/ck-seat.c:279 msgid "There is no Seat to activate" msgstr "ŠŠµŃ‚ рабочих мест Š“Š»Ń активации" #: src/ck-seat.c:285 msgid "Activation is not supported for this kind of seat" msgstr "Š”Š»Ń ŃŃ‚Š¾Š³Š¾ типа рабочего места Š°ŠŗŃ‚ŠøŠ²Š°Ń†ŠøŃ невозможна" #: src/ck-seat.c:290 msgid "Unknown session id" msgstr "ŠŠµŠøŠ·Š²ŠµŃŃ‚Š½Ń‹Š¹ иГентификатор сессии" #: src/ck-seat.c:301 src/ck-seat.c:338 src/ck-vt-monitor.c:128 msgid "Unable to activate session" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š°ŠŗŃ‚ŠøŠ²ŠøŃ€Š¾Š²Š°Ń‚ŃŒ ŃŠµŃŃŠøŃŽ" #: src/ck-seat.c:444 msgid "Unable to change VT for seat" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠøŠ·Š¼ŠµŠ½ŠøŃ‚ŃŒ Š’Š¢ Š“Š»Ń рабочего места" #: src/ck-seat.c:746 msgid "Session is not attached to this seat" msgstr "Š”ŠµŃŃŠøŃ не ŠæŃ€ŠøŠ²ŃŠ·Š°Š½Š° Šŗ ŃŃ‚Š¾Š¼Ńƒ Ń€Š°Š±Š¾Ń‡ŠµŠ¼Ńƒ Š¼ŠµŃŃ‚Ńƒ" #: src/ck-seat.c:1045 msgid "Seat has no sessions" msgstr "Š£ рабочего места нет сессий" #: src/main.c:230 msgid "Enable debugging code" msgstr "Š’ŠŗŠ»ŃŽŃ‡ŠøŃ‚ŃŒ коГ Š“Š»Ń отлаГки" #: src/main.c:231 msgid "Don't become a daemon" msgstr "ŠŠµ ŃŃ‚Š°Š½Š¾Š²ŠøŃ‚ŃŒŃŃ Гемоном" #: src/main.c:232 msgid "Exit after a time - for debugging" msgstr "Выйти через некоторое Š²Ń€ŠµŠ¼Ń - Š“Š»Ń отлаГки" #: src/main.c:257 tools/ck-collect-session-info.c:499 msgid "You must be root to run this program" msgstr "Š”Š»Ń запуска ŃŃ‚Š¾Š¹ программы необхоГимо Š±Ń‹Ń‚ŃŒ root" #: src/main.c:261 msgid "Console kit daemon" msgstr "Демон Console kit" #: src/ck-vt-monitor.c:109 msgid "Session is already active" msgstr "Š”ŠµŃŃŠøŃ уже активна" #: src/ck-vt-monitor.c:117 src/ck-vt-monitor.c:150 msgid "No consoles available" msgstr "ŠŠµŃ‚ Š“Š¾ŃŃ‚ŃƒŠæŠ½Ń‹Ń… консолей" #: src/ck-manager.c:1011 #, c-format msgid "Not Authorized: %s" msgstr "ŠŠµ авторизован: %s" #: src/ck-manager.c:1018 msgid "Authorization is required" msgstr "Š¢Ń€ŠµŠ±ŃƒŠµŃ‚ŃŃ Š°Š²Ń‚Š¾Ń€ŠøŠ·Š°Ń†ŠøŃ" #: src/ck-manager.c:1021 msgid "Not Authorized" msgstr "ŠŠµ авторизован" #: src/ck-manager.c:1491 #, c-format msgid "Unable to %s system: %s" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ %s ŃŠøŃŃ‚ŠµŠ¼Ńƒ: %s" #: src/ck-manager.c:1544 src/ck-manager.c:1651 src/ck-manager.c:1906 #: src/ck-manager.c:2038 src/ck-manager.c:2170 msgid "Attempting to perform a system action while one is in progress" msgstr "ŠŸŠ¾ŠæŃ‹Ń‚ŠŗŠ° Š·Š°ŠæŃƒŃŃ‚ŠøŃ‚ŃŒ системное Гействие во Š²Ń€ŠµŠ¼Ń его Š²Ń‹ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ" #: src/ck-manager.c:1556 msgid "failed to allocate memory to perform restart" msgstr "не уГалось Š²Ń‹Š“ŠµŠ»ŠøŃ‚ŃŒ ŠæŠ°Š¼ŃŃ‚ŃŒ Š“Š»Ń ŠæŠµŃ€ŠµŠ·Š°ŠæŃƒŃŠŗŠ°" #: src/ck-manager.c:1603 src/ck-manager.c:1703 src/ck-manager.c:1760 #: src/ck-manager.c:1839 src/ck-manager.c:1966 src/ck-manager.c:2098 #: src/ck-manager.c:2230 msgid "Operation is being inhibited" msgstr "ŠžŠæŠµŃ€Š°Ń†ŠøŃ Š±Š»Š¾ŠŗŠøŃ€ŃƒŠµŃ‚ŃŃ" #: src/ck-manager.c:1663 msgid "failed to allocate memory to perform shutdown" msgstr "не уГалось Š²Ń‹Š“ŠµŠ»ŠøŃ‚ŃŒ ŠæŠ°Š¼ŃŃ‚ŃŒ Š“Š»Ń Š¾Ń‚ŠŗŠ»ŃŽŃ‡ŠµŠ½ŠøŃ" #: src/ck-manager.c:1918 msgid "failed to allocate memory to perform suspend" msgstr "не уГалось Š²Ń‹Š“ŠµŠ»ŠøŃ‚ŃŒ ŠæŠ°Š¼ŃŃ‚ŃŒ Š“Š»Ń перехоГа в Š¶Š“ŃƒŃ‰ŠøŠ¹ режим" #: src/ck-manager.c:2050 msgid "failed to allocate memory to perform hibernate" msgstr "не уГалось Š²Ń‹Š“ŠµŠ»ŠøŃ‚ŃŒ ŠæŠ°Š¼ŃŃ‚ŃŒ Š“Š»Ń перехоГа в ŃŠæŃŃ‰ŠøŠ¹ режим" #: src/ck-manager.c:2182 msgid "failed to allocate memory to perform hybrid sleep" msgstr "не уГалось Š²Ń‹Š“ŠµŠ»ŠøŃ‚ŃŒ ŠæŠ°Š¼ŃŃ‚ŃŒ Š“Š»Ń перехоГа в режим гибриГного сна" #: src/ck-manager.c:2323 src/ck-manager.c:2350 msgid "Error creating the inhibit lock" msgstr "ŠžŃˆŠøŠ±ŠŗŠ° при созГании блокировки" #: src/ck-manager.c:2328 src/ck-manager.c:2390 msgid "Inhibit manager failed to initialize" msgstr "ŠŠµ уГалось ŠøŠ½ŠøŃ†ŠøŠ°Š»ŠøŠ·ŠøŃ€Š¾Š²Š°Ń‚ŃŒ менеГжер блокировок" #: src/ck-manager.c:2344 msgid "Invalid input when creating inhibit lock" msgstr "ŠŠµŠŗŠ¾Ń€Ń€ŠµŠŗŃ‚Š½Ń‹Š¹ ввоГ при созГании блокировки" #: src/ck-manager.c:2347 msgid "Unable to create inhibit lock, insufficient memory" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°Ń‚ŃŒ Š±Š»Š¾ŠŗŠøŃ€Š¾Š²ŠŗŃƒ: неГостаточно ŠæŠ°Š¼ŃŃ‚Šø" #: src/ck-manager.c:2397 msgid "There is nothing currently inhibited" msgstr "Š’ Ганный момент ничего не Š±Š»Š¾ŠŗŠøŃ€ŃƒŠµŃ‚ся" #: src/ck-manager.c:3059 src/ck-manager.c:3143 src/ck-manager.c:3200 msgid "Unable to get information about the calling process" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃŽ о Š²Ń‹Š·Ń‹Š²Š°ŃŽŃ‰ŠµŠ¼ процессе" #: src/ck-manager.c:3073 src/ck-manager.c:3421 src/ck-session.c:476 #: src/ck-session.c:525 #, c-format msgid "Unable to lookup information about calling process '%d'" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃŽ о Š²Ń‹Š·Ń‹Š²Š°ŃŽŃ‰ŠµŠ¼ процессе '%d'" #: src/ck-manager.c:3084 src/ck-manager.c:3091 src/ck-manager.c:3370 msgid "Unable to find session for cookie" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ найти ŃŠµŃŃŠøŃŽ Š“Š»Ń cookie" #: src/ck-manager.c:3126 msgid "pid must be > 1" msgstr "PID Голжен Š±Ń‹Ń‚ŃŒ > 1" #: src/ck-manager.c:3151 #, c-format msgid "Unable to lookup session information for process '%d'" msgstr "ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ ŠøŠ½Ń„Š¾Ń€Š¼Š°Ń†ŠøŃŽ о сессии Š“Š»Ń процесса '%d'" #: src/ck-manager.c:3378 msgid "User ID does not match the owner of cookie" msgstr "ID ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŠµŠ»Ń не ŃŠ¾Š¾Ń‚Š²ŠµŃ‚ŃŃ‚Š²ŃƒŠµŃ‚ Š²Š»Š°Š“ŠµŠ»ŃŒŃ†Ńƒ cookie" #: src/ck-manager.c:3388 msgid "Process ID does not match the owner of cookie" msgstr "ID процесса не ŃŠ¾Š¾Ń‚Š²ŠµŃ‚ŃŃ‚Š²ŃƒŠµŃ‚ Š²Š»Š°Š“ŠµŠ»ŃŒŃ†Ńƒ cookie" #: src/ck-manager.c:3665 msgid "User has no sessions" msgstr "Š£ ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŠµŠ»Ń нет сессий" #: src/ck-manager.c:3729 src/ck-manager.c:3774 src/ck-manager.c:3807 #: src/ck-manager.c:3833 msgid "Invalid session" msgstr "ŠŠµŠŗŠ¾Ń€Ń€ŠµŠŗŃ‚Š½Š°Ń ŃŠµŃŃŠøŃ" #: src/ck-manager.c:3734 src/ck-manager.c:3741 msgid "Invalid seat" msgstr "ŠŠµŠŗŠ¾Ń€Ń€ŠµŠŗŃ‚Š½Š¾Šµ рабочее место" #: src/ck-manager.c:3781 msgid "Session is not attached to a seat" msgstr "Š”ŠµŃŃŠøŃ не ŠæŃ€ŠøŠ²ŃŠ·Š°Š½Š° Šŗ Ń€Š°Š±Š¾Ń‡ŠµŠ¼Ńƒ Š¼ŠµŃŃ‚Ńƒ" #: src/ck-manager.c:3862 src/ck-manager.c:3898 msgid "User has no seats" msgstr "Š£ ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŠµŠ»Ń нет рабочих мест" #: src/ck-manager.c:3924 msgid "There are no sessions" msgstr "ŠŠµŃ‚ сессий" #: src/ck-session.c:482 msgid "Only session owner may set idle hint state" msgstr "Только влаГелец сессии может ŃƒŃŃ‚Š°Š½Š°Š²Š»ŠøŠ²Š°Ń‚ŃŒ маркер ŠæŃ€Š¾ŃŃ‚Š¾Ń" #: src/ck-session.c:531 msgid "Only session owner may set locked hint state" msgstr "Только влаГелец сессии может ŃƒŃŃ‚Š°Š½Š°Š²Š»ŠøŠ²Š°Ń‚ŃŒ маркер блокировки" #: src/ck-session.c:890 msgid "" "Activate signal not handeled. Session not attached to seat, or the seat " "doesn't support activation changes" msgstr "" "Дигнал активации не Š¾Š±Ń€Š°Š±Š°Ń‚Ń‹Š²Š°ŠµŃ‚ŃŃ. Š”ŠµŃŃŠøŃ не ŠæŃ€ŠøŠ²ŃŠ·Š°Š½Š° Šŗ Ń€Š°Š±Š¾Ń‡ŠµŠ¼Ńƒ Š¼ŠµŃŃ‚Ńƒ, " "или рабочее место не поГГерживает ŠøŠ·Š¼ŠµŠ½ŠµŠ½ŠøŃ активации" #: src/ck-session.c:1318 msgid "Failed to create the XDG_RUNTIME_DIR" msgstr "ŠŠµ уГалось ŃŠ¾Š·Š“Š°Ń‚ŃŒ XDG_RUNTIME_DIR" #: src/ck-session.c:1635 msgid "Server managed devices not supported" msgstr "Š£ŠæŃ€Š°Š²Š»ŃŠµŠ¼Ń‹Šµ сервером ŃƒŃŃ‚Ń€Š¾Š¹ŃŃ‚Š²Š° не ŠæŠ¾Š“Š“ŠµŃ€Š¶ŠøŠ²Š°ŃŽŃ‚ŃŃ" #: src/ck-session.c:1641 msgid "Failed to get uid of dbus caller" msgstr "ŠŠµ уГалось ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ UID клиента DBus" #: src/ck-session.c:1658 msgid "Failed to replace the current session controller" msgstr "ŠŠµ уГалось Š·Š°Š¼ŠµŠ½ŠøŃ‚ŃŒ Ń‚ŠµŠŗŃƒŃ‰ŠøŠ¹ контроллер сессии" #: src/ck-session.c:1660 msgid "Session controller already present" msgstr "ŠšŠ¾Š½Ń‚Ń€Š¾Š»Š»ŠµŃ€ сессии уже ŃŃƒŃ‰ŠµŃŃ‚Š²ŃƒŠµŃ‚" #: src/ck-session.c:1682 msgid "Only the session controller may use this function" msgstr "Только контроллер сессии может ŠøŃŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŃŒ эту Ń„ŃƒŠ½ŠŗŃ†ŠøŃŽ" #: src/ck-session.c:1775 src/ck-session.c:1822 src/ck-session.c:1854 msgid "Only the session controller may call this function" msgstr "Только контроллер сессии может Š²Ń‹Š·Ń‹Š²Š°Ń‚ŃŒ эту Ń„ŃƒŠ½ŠŗŃ†ŠøŃŽ" #: src/ck-session.c:1781 msgid "Device has already been requested" msgstr "Устройство уже было Š·Š°ŠæŃ€Š¾ŃˆŠµŠ½Š¾" #: src/ck-session.c:1788 msgid "Failed to create device" msgstr "ŠŠµ уГалось ŃŠ¾Š·Š“Š°Ń‚ŃŒ ŃƒŃŃ‚Ń€Š¾Š¹ŃŃ‚Š²Š¾" #: src/ck-session.c:1795 msgid "Failed to get file descriptor for device" msgstr "ŠŠµ уГалось ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ файловый Гескриптор ŃƒŃŃ‚Ń€Š¾Š¹ŃŃ‚Š²Š°" #: src/ck-session.c:1829 src/ck-session.c:1861 msgid "Device doesn't exist" msgstr "Устройство не ŃŃƒŃ‰ŠµŃŃ‚Š²ŃƒŠµŃ‚" #. TRANSLATORS: This is letting the user know that cgmanager #. * support was compiled in, but the cgmanager daemon isn't #. * running. #. #: src/ck-process-group.c:111 msgid "" "Failed to open connection to cgmanager. Is the cgmanager daemon running?" msgstr "ŠŠµ уГалось ŠæŠ¾Š“ŠŗŠ»ŃŽŃ‡ŠøŃ‚ŃŒŃŃ Šŗ cgmanager. Š—Š°ŠæŃƒŃ‰ŠµŠ½ ли Гемон cgmanager?" #. TRANSLATORS: There is an error with cgmanager, we're just #. * printing it out. Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:127 #, c-format msgid "There was an error while initializing cgmanager, the error was: %s" msgstr "ŠŸŃ€Šø инициализации cgmanager ŠæŃ€Š¾ŠøŠ·Š¾ŃˆŠ»Š° ошибка: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:234 #, c-format msgid "Failed to create cgroup, the error was: %s" msgstr "ŠŠµ уГалось ŃŠ¾Š·Š“Š°Ń‚ŃŒ cgroup: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:251 #, c-format msgid "" "Failed to change owner of the new cgroup to owner of the session leader, the " "error was: %s" msgstr "" "ŠŠµ уГалось ŃŠ¼ŠµŠ½ŠøŃ‚ŃŒ Š²Š»Š°Š“ŠµŠ»ŃŒŃ†Š° новой cgroup на Š²Š»Š°Š“ŠµŠ»ŃŒŃ†Š° лиГера сессии: %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:270 #, c-format msgid "" "Failed to move the session leader process to 'cpuacct' cgroup, the error " "was: %s" msgstr "ŠŠµ уГалось ŠæŠµŃ€ŠµŠ¼ŠµŃŃ‚ŠøŃ‚ŃŒ процесс-лиГер сессии в cgroup 'cpuacct': %s" #. TRANSLATORS: Please ensure you keep the %s in the #. * string somewhere. It's the detailed error message from #. * cgmanager. #. #: src/ck-process-group.c:309 #, c-format msgid "Failed to get the session id from cgmanager, the error was: %s" msgstr "ŠŠµ уГалось ŠæŠ¾Š»ŃƒŃ‡ŠøŃ‚ŃŒ иГентификатор сессии от cgmanager: %s" #: tools/ck-history.c:903 tools/list-sessions.c:414 msgid "Version of this application" msgstr "Š’ŠµŃ€ŃŠøŃ ŃŃ‚Š¾Š³Š¾ ŠæŃ€ŠøŠ»Š¾Š¶ŠµŠ½ŠøŃ" #: tools/ck-history.c:904 msgid "Show listing of frequent users" msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ список частых ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŠµŠ»ŠµŠ¹" #: tools/ck-history.c:905 msgid "Show listing of last logged in users" msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ список послеГних Š²Š¾ŃˆŠµŠ“ŃˆŠøŃ… ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŠµŠ»ŠµŠ¹" #: tools/ck-history.c:906 msgid "Show 'last' compatible listing of last logged in users" msgstr "" "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ 'послеГний' совместимый список послеГних Š²Š¾ŃˆŠµŠ“ŃˆŠøŃ… ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŠµŠ»ŠµŠ¹" #: tools/ck-history.c:907 msgid "Show full event log" msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ полный Š¶ŃƒŃ€Š½Š°Š» событий" #: tools/ck-history.c:908 msgid "Show entries for the specified seat" msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ записи Š“Š»Ń указанного рабочего места" #: tools/ck-history.c:908 msgid "SEAT" msgstr "ŠœŠ•Š”Š¢Šž" #: tools/ck-history.c:909 msgid "Show entries for the specified session type" msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ записи Š“Š»Ń указанного типа сессии" #: tools/ck-history.c:909 msgid "TYPE" msgstr "ТИП" #: tools/ck-history.c:910 msgid "Show entries for the specified user" msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ записи Š“Š»Ń указанного ŠæŠ¾Š»ŃŒŠ·Š¾Š²Š°Ń‚ŠµŠ»Ń" #: tools/ck-history.c:910 msgid "NAME" msgstr "ИМЯ" #: tools/ck-history.c:911 msgid "Show entries since the specified time (ISO 8601 format)" msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ записи Š½Š°Ń‡ŠøŠ½Š°Ń с указанного времени (в формате ISO 8601)" #: tools/ck-history.c:911 msgid "DATETIME" msgstr "Š’Š Š•ŠœŠÆ" #: tools/ck-get-x11-display-device.c:246 msgid "display name" msgstr "ŠæŠ¾ŠŗŠ°Š·Š°Ń‚ŃŒ ŠøŠ¼Ń" consolekit2-1.2.6/src/000077500000000000000000000000001446640754400145615ustar00rootroot00000000000000consolekit2-1.2.6/src/.gitignore000066400000000000000000000003241446640754400165500ustar00rootroot00000000000000*.la *.lo *.o .deps .libs Makefile Makefile.in console-kit-daemon test-event-logger test-tty-idle-monitor test-vt-monitor test-inhibit ck-marshal.c ck-marshal.h ck-manager-glue.h ck-seat-glue.h ck-session-glue.h consolekit2-1.2.6/src/Makefile.am000066400000000000000000000202601446640754400166150ustar00rootroot00000000000000## We require new-style dependency handling. AUTOMAKE_OPTIONS = 1.7 NULL = SUBDIRS = \ $(NULL) AM_CFLAGS = \ -I. \ -I$(srcdir) \ $(GLIB_CFLAGS) \ $(GIO_CFLAGS) \ $(GIO_UNIX_CFLAGS) \ $(POLKIT_CFLAGS) \ $(LIBDBUS_CFLAGS) \ $(CGMANAGER_CFLAGS) \ $(LIBUDEV_CFLAGS) \ $(LIBDRM_CFLAGS) \ $(SELINUX_CFLAGS) \ $(LIBEVDEV_CFLAGS) \ $(RBAC_CFLAGS) \ $(LIBX11_CFLAGS) \ -DPREFIX=\""$(prefix)"\" \ -DBINDIR=\""$(bindir)"\" \ -DLIBDIR=\""$(libdir)"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DLOCALSTATEDIR=\""$(localstatedir)"\" \ -DRUNDIR=\""$(RUNDIR)"\" \ -DCONSOLE_KIT_PID_FILE=\""$(CONSOLE_KIT_PID_FILE)"\" \ -DLOCALEDIR=\"$(localedir)\" \ $(NULL) CONSOLE_KIT_LIBS = \ $(CK2_LIBS) \ $(GLIB_LIBS) \ $(GIO_LIBS) \ $(GIO_UNIX_LIBS) \ $(LIBDBUS_LIBS) \ $(SELINUX_LIBS) \ $(LIBEVDEV_LIBS) \ $(POLKIT_LIBS) \ $(RBAC_LIBS) \ $(CGMANAGER_LIBS) \ $(LIBUDEV_LIBS) \ $(LIBDRM_LIBS) \ $(LIBX11_LIBS) noinst_LTLIBRARIES = \ libck.la \ libck-event-log.la \ $(NULL) libck_event_log_la_SOURCES = \ ck-log-event.h \ ck-log-event.c \ $(NULL) libck_la_SOURCES = \ ck-sysdeps.h \ ck-sysdeps-unix.c \ $(NULL) libck_la_LIBADD = $(CONSOLE_KIT_LIBS) if CK_COMPILE_LINUX libck_la_SOURCES += \ ck-sysdeps-linux.c \ $(NULL) libck_la_LIBADD += $(SELINUX_LIBS) endif if CK_COMPILE_SOLARIS libck_la_SOURCES += \ ck-sysdeps-solaris.c \ $(NULL) libck_la_LIBADD += -lscf endif if CK_COMPILE_FREEBSD libck_la_SOURCES += \ ck-sysdeps-freebsd.c \ $(NULL) libck_la_LIBADD += $(KVM_LIBS) endif if CK_COMPILE_DRAGONFLY libck_la_SOURCES += \ ck-sysdeps-dragonfly.c \ $(NULL) libck_la_LIBADD += $(KVM_LIBS) endif if CK_COMPILE_OPENBSD libck_la_SOURCES += \ ck-sysdeps-openbsd.c \ $(NULL) libck_la_LIBADD += $(KVM_LIBS) endif if CK_COMPILE_GNU libck_la_SOURCES += \ ck-sysdeps-gnu.c \ $(NULL) libck_la_LIBADD += -lps endif if CK_COMPILE_NETBSD libck_la_SOURCES += \ ck-sysdeps-netbsd.c \ $(NULL) libck_la_LIBADD += $(KVM_LIBS) endif EXTRA_libck_la_SOURCES = \ ck-sysdeps-linux.c \ ck-sysdeps-solaris.c \ ck-sysdeps-freebsd.c \ ck-sysdeps-netbsd.c \ ck-sysdeps-gnu.c \ $(NULL) sbin_PROGRAMS = \ console-kit-daemon \ $(NULL) BUILT_SOURCES = \ ck-manager-generated.h \ ck-manager-generated.c \ ck-seat-generated.h \ ck-seat-generated.c \ ck-session-generated.h \ ck-session-generated.c \ ck-marshal.c \ ck-marshal.h \ $(NULL) dbusifdir = $(datadir)/dbus-1/interfaces dbusif_DATA = \ org.freedesktop.ConsoleKit.Manager.xml \ org.freedesktop.ConsoleKit.Seat.xml \ org.freedesktop.ConsoleKit.Session.xml \ $(NULL) ck-manager-generated.c ck-manager-generated.h : org.freedesktop.ConsoleKit.Manager.xml Makefile.am gdbus-codegen \ --c-namespace=ConsoleKit \ --interface-prefix=org.freedesktop.ConsoleKit. \ --generate-c-code=ck-manager-generated \ $(srcdir)/org.freedesktop.ConsoleKit.Manager.xml ck-seat-generated.c ck-seat-generated.h : org.freedesktop.ConsoleKit.Seat.xml Makefile.am gdbus-codegen \ --c-namespace=ConsoleKit \ --interface-prefix=org.freedesktop.ConsoleKit. \ --generate-c-code=ck-seat-generated \ $(srcdir)/org.freedesktop.ConsoleKit.Seat.xml ck-session-generated.c ck-session-generated.h : org.freedesktop.ConsoleKit.Session.xml Makefile.am gdbus-codegen \ --c-namespace=ConsoleKit \ --interface-prefix=org.freedesktop.ConsoleKit. \ --generate-c-code=ck-session-generated \ $(srcdir)/org.freedesktop.ConsoleKit.Session.xml ck-marshal.c: ck-marshal.list echo "#include \"ck-marshal.h\"" > $@ && \ @GLIB_GENMARSHAL@ $< --prefix=ck_marshal --body >> $@ ck-marshal.h: ck-marshal.list @GLIB_GENMARSHAL@ $< --prefix=ck_marshal --header > $@ console_kit_daemon_SOURCES = \ main.c \ ck-manager.h \ ck-manager.c \ ck-vt-monitor.h \ ck-vt-monitor.c \ ck-tty-idle-monitor.h \ ck-tty-idle-monitor.c \ ck-file-monitor.h \ ck-job.h \ ck-job.c \ ck-seat.h \ ck-seat.c \ ck-session-leader.h \ ck-session-leader.c \ ck-session.h \ ck-session.c \ ck-log.h \ ck-log.c \ ck-run-programs.c \ ck-run-programs.h \ ck-event-logger.c \ ck-event-logger.h \ ck-inhibit.c \ ck-inhibit.h \ ck-inhibit-manager.c \ ck-inhibit-manager.h \ ck-process-group.h \ ck-process-group.c \ ck-device.h \ $(BUILT_SOURCES) \ $(NULL) if ENABLE_INOTIFY FILE_MONITOR_BACKEND = ck-file-monitor-inotify.c else FILE_MONITOR_BACKEND = ck-file-monitor-dummy.c endif console_kit_daemon_SOURCES += $(FILE_MONITOR_BACKEND) if USE_UDEV_BACKEND console_kit_daemon_SOURCES += \ ck-device-udev.c \ $(NULL) else console_kit_daemon_SOURCES += \ ck-device-none.c \ $(NULL) endif EXTRA_console_kit_daemon_SOURCES = \ ck-file-monitor-inotify.c \ ck-file-monitor-dummy.c \ $(NULL) console_kit_daemon_LDADD = \ $(CONSOLE_KIT_LIBS) \ libck.la \ libck-event-log.la \ $(NULL) if BUILD_TESTS noinst_PROGRAMS = \ test-event-logger \ test-tty-idle-monitor \ test-vt-monitor \ test-inhibit \ test-session \ test-seat \ test-manager \ ck-collect-session-info \ test-session-leader \ $(NULL) test_event_logger_SOURCES = \ ck-event-logger.h \ ck-event-logger.c \ test-event-logger.c \ $(NULL) test_event_logger_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(POLKIT_LIBS) \ $(RBAC_LIBS) \ libck-event-log.la \ $(NULL) test_vt_monitor_SOURCES = \ ck-vt-monitor.h \ ck-vt-monitor.c \ test-vt-monitor.c \ $(NULL) test_vt_monitor_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(POLKIT_LIBS) \ libck.la \ $(NULL) test_tty_idle_monitor_SOURCES = \ ck-tty-idle-monitor.h \ ck-tty-idle-monitor.c \ ck-file-monitor.h \ $(FILE_MONITOR_BACKEND) \ test-tty-idle-monitor.c \ $(NULL) test_tty_idle_monitor_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(POLKIT_LIBS) \ libck.la \ $(NULL) test_inhibit_CFLAGS = \ $(AM_CFLAGS) \ -URUNDIR \ -DRUNDIR=\"/tmp\" \ $(NULL) test_inhibit_SOURCES = \ ck-marshal.h \ ck-marshal.c \ ck-inhibit.c \ ck-inhibit.h \ ck-inhibit-manager.c \ ck-inhibit-manager.h \ test-inhibit.c \ $(NULL) test_inhibit_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(POLKIT_LIBS) \ libck.la \ $(NULL) test_session_CFLAGS = \ $(AM_CFLAGS) \ -URUNDIR \ -DRUNDIR=\"/tmp\" \ $(NULL) test_session_SOURCES = \ $(BUILT_SOURCES) \ test-session.c \ $(NULL) test_session_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(POLKIT_LIBS) \ libck.la \ $(NULL) test_seat_CFLAGS = \ $(AM_CFLAGS) \ -URUNDIR \ -DRUNDIR=\"/tmp\" \ $(NULL) test_seat_SOURCES = \ $(BUILT_SOURCES) \ test-seat.c \ $(NULL) test_seat_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(POLKIT_LIBS) \ libck.la \ $(NULL) test_manager_CFLAGS = \ $(AM_CFLAGS) \ -URUNDIR \ -DRUNDIR=\"/tmp\" \ $(NULL) test_manager_SOURCES = \ $(BUILT_SOURCES) \ test-manager.c \ $(NULL) test_manager_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(POLKIT_LIBS) \ libck.la \ $(NULL) ck_collect_session_info_CFLAGS = \ $(AM_CFLAGS) \ $(NULL) ck_collect_session_info_SOURCES = \ $(BUILT_SOURCES) \ mock-ck-collect-session-info.c \ $(NULL) ck_collect_session_info_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(NULL) test_session_leader_CFLAGS = \ $(AM_CFLAGS) \ -ULIBEXECDIR \ -DLIBEXECDIR=\".\" \ $(NULL) test_session_leader_SOURCES = \ $(BUILT_SOURCES) \ ck-job.h \ ck-job.c \ ck-session-leader.c \ ck-session-leader.h \ test-session-leader.c \ $(NULL) test_session_leader_LDADD = \ $(CONSOLE_KIT_LIBS) \ libck.la \ $(NULL) endif # BUILD_TESTS EXTRA_DIST = \ ck-marshal.list \ $(dbusif_DATA) \ valgrind.sh \ $(NULL) if BUILD_TESTS EXTRA_DIST += \ test-open-session \ test-open-session-with-parameters \ test-session \ test-seat \ test-session-leader \ test-manager \ ck-collect-session-info \ $(NULL) endif # BUILD_TESTS CLEANFILES = $(BUILT_SOURCES) MAINTAINERCLEANFILES = \ *~ \ Makefile.in install-data-local: -mkdir -p $(DESTDIR)$(sysconfdir)/ConsoleKit/run-session.d -mkdir -p $(DESTDIR)$(libdir)/ConsoleKit/run-session.d -mkdir -p $(DESTDIR)$(sysconfdir)/ConsoleKit/run-seat.d -mkdir -p $(DESTDIR)$(libdir)/ConsoleKit/run-seat.d -mkdir -p $(DESTDIR)$(RUNDIR)/ConsoleKit -mkdir -p $(DESTDIR)$(localstatedir)/log/ConsoleKit consolekit2-1.2.6/src/ck-device-none.c000066400000000000000000000060761446640754400175250ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2016, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include /* For TRACE */ #include "ck-sysdeps.h" #include "ck-device.h" static void ck_device_finalize (GObject *object); struct _CkDevice { GObject parent_instance; }; G_DEFINE_TYPE (CkDevice, ck_device, G_TYPE_OBJECT) static void ck_device_class_init (CkDeviceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_device_finalize; } static void ck_device_init (CkDevice *device) { } static void ck_device_finalize (GObject *object) { G_OBJECT_CLASS (ck_device_parent_class)->finalize (object); } CkDevice* ck_device_new (guint major, guint minor, gboolean active) { return NULL; } void ck_device_set_active (CkDevice *device, gboolean active) { } gboolean ck_device_get_active (CkDevice *device) { return FALSE; } guint ck_device_get_major (CkDevice *device) { return 0; } guint ck_device_get_minor (CkDevice *device) { return 0; } gint ck_device_get_fd (CkDevice *device) { return -1; } CkDeviceCategory ck_device_get_category (CkDevice *device) { return DEVICE_OTHER; } gboolean ck_device_compare_devices (CkDevice *device1, CkDevice *device2) { return FALSE; } gboolean ck_device_compare (CkDevice *device, guint major, guint minor) { return FALSE; } gboolean ck_device_is_server_managed (void) { return FALSE; } consolekit2-1.2.6/src/ck-device-udev.c000066400000000000000000000327301446640754400175250ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2016, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_LINUX_INPUT_H #include #endif #ifdef HAVE_LIBDRM #include #endif #ifdef HAVE_SYS_SYSMACROS_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_LIBUDEV_H #include #endif #ifdef HAVE_DEVATTR_H #include #endif #ifdef HAVE_LIBPROP_PROPLIB_H #include #endif #ifdef HAVE_SYS_MKDEV_H #include #endif #ifdef HAVE_LIBEVDEV_H #include "libevdev.h" #endif /* For TRACE */ #include "ck-sysdeps.h" #include "ck-device.h" /* We may not have the evdev header because of license issues, so * we'll define the symbol here */ #ifndef EVIOCREVOKE #define EVIOCREVOKE _IOW('E', 0x91, int) #endif static void ck_device_finalize (GObject *object); struct _CkDevice { GObject parent_instance; guint major; guint minor; struct udev_device *udevice; gchar *devnode; CkDeviceCategory category; gint fd; gboolean state; }; static struct udev *dev = NULL; G_DEFINE_TYPE (CkDevice, ck_device, G_TYPE_OBJECT) static void ck_device_class_init (CkDeviceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_device_finalize; } static void ck_device_init (CkDevice *device) { device->fd = -1; } static void ck_device_finalize (GObject *object) { CkDevice *device = CK_DEVICE (object); /* Always revoke/drop master before we are removed */ ck_device_set_active (device, FALSE); if (device->udevice != NULL) { udev_device_unref (device->udevice); } if (device->fd >= 0) { g_close (device->fd, NULL); } g_free (device->devnode); G_OBJECT_CLASS (ck_device_parent_class)->finalize (object); } static gboolean ck_device_evdev_revoke (gint fd) { errno = 0; if (fd < 0) { return FALSE; } if (ioctl (fd, EVIOCREVOKE, NULL) == -1) { g_warning ("failed to revoke access. Error: %s", g_strerror(errno)); return FALSE; } return TRUE; } static gboolean change_drm_master (gint fd, gulong request) { errno = 0; if (fd < 0) { return FALSE; } if (ioctl (fd, request, NULL) == -1) { g_warning ("failed to change drm master setting. Error: %s", g_strerror(errno)); return FALSE; } return TRUE; } static gint ck_device_drm_drop_master (gint fd) { TRACE (); return change_drm_master (fd, DRM_IOCTL_DROP_MASTER); } static gboolean ck_device_drm_set_master (gint fd) { TRACE (); return change_drm_master (fd, DRM_IOCTL_SET_MASTER); } static gint ck_device_open (CkDevice *device, gboolean active) { gint fd = -1; TRACE (); if (device == NULL || device->udevice == NULL || device->devnode == NULL) { g_debug ("invalid device"); return -1; } g_debug ("opening devnode: %s", device->devnode); fd = g_open (device->devnode, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK, S_IRUSR|S_IWUSR); if (fd < 0) { g_debug ("failed to open device"); return -1; } switch (device->category) { case DEVICE_DRM: if (active) { if (!ck_device_drm_set_master (fd)) { g_debug ("failed to call drm set master"); g_close (fd, NULL); return -1; } } else { ck_device_drm_drop_master (fd); } break; case DEVICE_EVDEV: if (active == FALSE) { ck_device_evdev_revoke (fd); } break; default: g_debug ("ck_device_open: Device type not supported"); break; } return fd; } static struct udev_device* ck_device_get_udevice_from_devnum (guint major, guint minor) { #if defined(HAVE_DEVATTR_H) struct udev_enumerate *enumerate; struct udev_list_entry *current; struct udev_device *udevice = NULL; prop_dictionary_t dict; gchar majorbuf[16]; gchar minorbuf[16]; enumerate = udev_enumerate_new (dev); if (enumerate == NULL) { g_warning ("ck_device_get_udevice_from_devnum: failed to call udev_enumerate_new"); return NULL; } memset (majorbuf, 0, sizeof(majorbuf)); memset (minorbuf, 0, sizeof(minorbuf)); g_snprintf (majorbuf, 15, "%d", major); g_snprintf (minorbuf, 15, "%d", minor); udev_enumerate_add_match_expr (enumerate, "major", majorbuf); udev_enumerate_add_match_expr (enumerate, "minor", minorbuf); if (udev_enumerate_scan_devices (enumerate) != 0) { /* failed to scan devices */ udev_enumerate_unref (enumerate); return NULL; } current = udev_enumerate_get_list_entry (enumerate); if (current == NULL) { /* No device with that major/minor */ udev_enumerate_unref (enumerate); return NULL; } udev_list_entry_foreach (current, current) { udevice = udev_list_entry_get_device (current); if (udevice == NULL) { continue; } dict = udev_device_get_dictionary (udevice); if (dict == NULL) { /* Why is there a device with no properties? */ udevice = NULL; continue; } /* found our device, create our ref */ udev_device_ref (udevice); break; } udev_enumerate_unref (enumerate); return udevice; #else return udev_device_new_from_devnum (dev, 'c', makedev (major, minor)); #endif } static gchar* udevice_get_device_name (struct udev_device *udevice) { #if defined(HAVE_DEVATTR_H) gchar *name; prop_dictionary_t dict; if (udevice == NULL) { return NULL; } dict = udev_device_get_dictionary (udevice); if (dict == NULL) { return NULL; } prop_dictionary_get_cstring (dict, "driver", &name); return name; #else return g_strdup (udev_device_get_sysname (udevice)); #endif } CkDevice* ck_device_new (guint major, guint minor, gboolean active) { CkDevice *device; const gchar *subsystem; const gchar *sysname; TRACE (); /* We create a single udev instance */ if (dev == NULL) { dev = udev_new (); if (dev == NULL) { return NULL; } } device = g_object_new (CK_TYPE_DEVICE, NULL); device->major = major; device->minor = minor; device->state = active; device->udevice = ck_device_get_udevice_from_devnum (major, minor); if (device->udevice == NULL) { g_warning ("failed to get a udev device, it probably doesn't exist"); g_object_unref (device); return NULL; } subsystem = udev_device_get_subsystem (device->udevice); sysname = udevice_get_device_name (device->udevice); device->devnode = g_strdup (udev_device_get_devnode (device->udevice)); g_debug ("major %d minor %d subsystem %s sysname %s devnode %s active ? %s", major, minor, subsystem, sysname, device->devnode, active ? "TRUE" : "FALSE"); /* Start with other device as a default, we have special things * we do with DRM and EVDEV devices so find and tag them */ device->category = DEVICE_OTHER; if (g_strcmp0 (subsystem, "drm") == 0) { if (g_str_has_prefix (sysname, "card")) { g_debug ("DEVICE_DRM"); device->category = DEVICE_DRM; } } else if (g_strcmp0 (subsystem, "input") == 0) { if (g_str_has_prefix (sysname, "event")) { g_debug ("DEVICE_EVDEV"); device->category = DEVICE_EVDEV; } } if (device->category != DEVICE_OTHER) { /* we don't do device management for anything but * DRM/EVDEV */ device->fd = ck_device_open (device, active); if (device->fd < 0 && active) { /* try again in an inactive state */ device->fd = ck_device_open (device, FALSE); } } return device; } void ck_device_set_active (CkDevice *device, gboolean active) { TRACE (); if (device == NULL) return; if (device->state == active) return; device->state = active; switch (device->category) { case DEVICE_DRM: if (active) { ck_device_drm_set_master (device->fd); } else { ck_device_drm_drop_master (device->fd); } break; case DEVICE_EVDEV: if (active) { /* close the old fd since it was revoked when * inactive */ g_close (device->fd, NULL); device->fd = ck_device_open (device, active); } else { ck_device_evdev_revoke (device->fd); } break; default: g_warning ("ck_device_set_active: Device type not supported"); break; } } gboolean ck_device_get_active (CkDevice *device) { return device->state; } guint ck_device_get_major (CkDevice *device) { return device->major; } guint ck_device_get_minor (CkDevice *device) { return device->minor; } gint ck_device_get_fd (CkDevice *device) { return device->fd; } CkDeviceCategory ck_device_get_category (CkDevice *device) { return device->category; } gboolean ck_device_compare_devices (CkDevice *device1, CkDevice *device2) { if (device1 == NULL || device2 == NULL) { return FALSE; } if (device1->major != device2->major) { return FALSE; } if (device1->minor != device2->minor) { return FALSE; } return TRUE; } gboolean ck_device_compare (CkDevice *device, guint major, guint minor) { if (device == NULL) { return FALSE; } if (device->major != major) { return FALSE; } if (device->minor != minor) { return FALSE; } return TRUE; } gboolean ck_device_is_server_managed (void) { return TRUE; } consolekit2-1.2.6/src/ck-device.h000066400000000000000000000067421446640754400165750ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2016, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CK_DEVICE_H_ #define CK_DEVICE_H_ #include #define CK_TYPE_DEVICE (ck_device_get_type ()) #define CK_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_DEVICE, CkDevice)) #define CK_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_DEVICE, CkDeviceClass)) #define CK_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_DEVICE)) #define CK_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_DEVICE)) #define CK_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_DEVICE, CkDeviceClass)) typedef enum { DEVICE_DRM, DEVICE_EVDEV, DEVICE_OTHER } CkDeviceCategory; typedef struct _CkDevice CkDevice; typedef struct { GObjectClass parent_class; } CkDeviceClass; GType ck_device_get_type (void); CkDevice *ck_device_new (guint major, guint minor, gboolean active); void ck_device_set_active (CkDevice *device, gboolean active); gboolean ck_device_get_active (CkDevice *device); guint ck_device_get_major (CkDevice *device); guint ck_device_get_minor (CkDevice *device); CkDeviceCategory ck_device_get_category (CkDevice *device); gint ck_device_get_fd (CkDevice *device); gboolean ck_device_compare_devices (CkDevice *device1, CkDevice *device2); gboolean ck_device_compare (CkDevice *device, guint major, guint minor); gboolean ck_device_is_server_managed (void); #endif /* CK_DEVICE_H_ */ consolekit2-1.2.6/src/ck-event-logger.c000066400000000000000000000345731446640754400177320ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-event-logger.h" #include "ck-log-event.h" #define CK_EVENT_LOGGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_EVENT_LOGGER, CkEventLoggerPrivate)) #define DEFAULT_LOG_FILENAME LOCALSTATEDIR "/log/ConsoleKit/history" struct CkEventLoggerPrivate { int fd; FILE *file; GThread *writer_thread; GAsyncQueue *event_queue; char *log_filename; }; enum { PROP_0, PROP_LOG_FILENAME }; static void ck_event_logger_finalize (GObject *object); G_DEFINE_TYPE (CkEventLogger, ck_event_logger, G_TYPE_OBJECT) GQuark ck_event_logger_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("ck_event_logger_error"); } return ret; } gboolean ck_event_logger_queue_event (CkEventLogger *event_logger, CkLogEvent *event, GError **error) { CkLogEvent *event_copy; gboolean ret; g_return_val_if_fail (CK_IS_EVENT_LOGGER (event_logger), FALSE); g_return_val_if_fail (event != NULL, FALSE); event_copy = ck_log_event_copy (event); g_async_queue_push (event_logger->priv->event_queue, event_copy); ret = TRUE; return ret; } /* Adapted from auditd auditd-event.c */ static gboolean open_log_file (CkEventLogger *event_logger) { int flags; int fd; int res; char *dirname; /* * Likely errors on rotate: ENFILE, ENOMEM, ENOSPC */ flags = O_WRONLY | O_APPEND; #ifdef O_NOFOLLOW flags |= O_NOFOLLOW; #endif dirname = g_path_get_dirname (event_logger->priv->log_filename); /* always make sure we have a directory */ errno = 0; res = g_mkdir_with_parents (dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (res < 0) { g_warning ("Unable to create directory %s (%s)", dirname, g_strerror (errno)); g_free (dirname); return FALSE; } g_free (dirname); retry: errno = 0; fd = g_open (event_logger->priv->log_filename, flags, 0600); if (fd < 0) { if (errno == ENOENT) { fd = g_open (event_logger->priv->log_filename, O_CREAT | O_EXCL | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd < 0) { g_warning ("Couldn't create log file %s (%s)", event_logger->priv->log_filename, g_strerror (errno)); return FALSE; } close (fd); fd = g_open (event_logger->priv->log_filename, flags, 0600); } else if (errno == ENFILE) { /* All system descriptors used, try again... */ goto retry; } if (fd < 0) { g_warning ("Couldn't open log file %s (%s)", event_logger->priv->log_filename, g_strerror (errno)); return FALSE; } } if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) { close (fd); g_warning ("Error setting log file CLOEXEC flag (%s)", g_strerror (errno)); return FALSE; } if (fchown (fd, 0, 0) == -1) { close (fd); g_warning ("Error setting owner of log file (%s)", g_strerror (errno)); return FALSE; } event_logger->priv->file = fdopen (fd, "a"); if (event_logger->priv->file == NULL) { g_warning ("Error setting up log descriptor (%s)", g_strerror (errno)); close (fd); return FALSE; } event_logger->priv->fd = fd; /* Set it to line buffering */ setlinebuf (event_logger->priv->file); return TRUE; } static void reopen_file_stream (CkEventLogger *event_logger) { /* fclose will also close the underlying fd */ if (event_logger->priv->file != NULL) { fclose (event_logger->priv->file); } /* FIXME: retries */ open_log_file (event_logger); } static void check_file_stream (CkEventLogger *event_logger) { int old_fd; struct stat old_stats; int new_fd; struct stat new_stats; old_fd = event_logger->priv->fd; if (fstat (old_fd, &old_stats) != 0) { g_warning ("Unable to stat file: %s", g_strerror (errno)); reopen_file_stream (event_logger); return; } new_fd = g_open (event_logger->priv->log_filename, O_RDONLY | O_NONBLOCK, 0600); if (new_fd == -1 || fstat (new_fd, &new_stats) < 0) { if (new_fd != -1) { /* only try to close the fd if it succeeded in * opening */ g_close (new_fd, NULL); } g_debug ("Unable to open or stat %s - will try to reopen", event_logger->priv->log_filename); reopen_file_stream (event_logger); return; } close (new_fd); if (old_stats.st_ino != new_stats.st_ino || old_stats.st_dev != new_stats.st_dev) { g_debug ("File %s has been replaced; writing to end of new file", event_logger->priv->log_filename); reopen_file_stream (event_logger); return; } } static gboolean write_log_for_event (CkEventLogger *event_logger, CkLogEvent *event) { GString *str; str = g_string_new (NULL); ck_log_event_to_string (event, str); g_debug ("Writing log for event: %s", str->str); check_file_stream (event_logger); if (event_logger->priv->file != NULL) { int rc; rc = fprintf (event_logger->priv->file, "%s\n", str->str); if (rc <= 0) { g_warning ("Record was not written to disk (%s)", g_strerror (errno)); } } else { g_warning ("Log file not open for writing"); } g_string_free (str, TRUE); return TRUE; } static void * writer_thread_start (CkEventLogger *event_logger) { CkLogEvent *event; while (1) { event = g_async_queue_pop (event_logger->priv->event_queue); if (event == NULL || event->type == CK_LOG_EVENT_NONE) { break; } write_log_for_event (event_logger, event); ck_log_event_free (event); } g_debug ("Writer thread received None event - exiting"); return NULL; } static void create_writer_thread (CkEventLogger *event_logger) { GError *error; g_debug ("Creating thread for log writing"); error = NULL; #if GLIB_CHECK_VERSION(2, 32, 0) event_logger->priv->writer_thread = g_thread_try_new ("writer_thread_start", (GThreadFunc)writer_thread_start, event_logger, &error); #else event_logger->priv->writer_thread = g_thread_create_full ((GThreadFunc)writer_thread_start, event_logger, 65536, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL, &error); #endif if (event_logger->priv->writer_thread == NULL) { g_debug ("Unable to create thread: %s", error->message); g_error_free (error); } } static void destroy_writer_thread (CkEventLogger *event_logger) { CkLogEvent event; event.type = CK_LOG_EVENT_NONE; g_debug ("Destroying writer thread"); g_async_queue_push (event_logger->priv->event_queue, &event); #if 1 g_debug ("Joining writer thread"); g_thread_join (event_logger->priv->writer_thread); #endif } static GObject * ck_event_logger_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { CkEventLogger *event_logger; event_logger = CK_EVENT_LOGGER (G_OBJECT_CLASS (ck_event_logger_parent_class)->constructor (type, n_construct_properties, construct_properties)); if (open_log_file (event_logger)) { create_writer_thread (event_logger); } return G_OBJECT (event_logger); } static void _ck_event_logger_set_log_filename (CkEventLogger *event_logger, const char *filename) { g_free (event_logger->priv->log_filename); event_logger->priv->log_filename = g_strdup (filename); } static void ck_event_logger_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { CkEventLogger *self; self = CK_EVENT_LOGGER (object); switch (prop_id) { case PROP_LOG_FILENAME: _ck_event_logger_set_log_filename (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ck_event_logger_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { CkEventLogger *self; self = CK_EVENT_LOGGER (object); switch (prop_id) { case PROP_LOG_FILENAME: g_value_set_string (value, self->priv->log_filename); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ck_event_logger_class_init (CkEventLoggerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_event_logger_finalize; object_class->constructor = ck_event_logger_constructor; object_class->get_property = ck_event_logger_get_property; object_class->set_property = ck_event_logger_set_property; g_object_class_install_property (object_class, PROP_LOG_FILENAME, g_param_spec_string ("log-filename", "log-filename", "log-filename", DEFAULT_LOG_FILENAME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_type_class_add_private (klass, sizeof (CkEventLoggerPrivate)); } static void ck_event_logger_init (CkEventLogger *event_logger) { event_logger->priv = CK_EVENT_LOGGER_GET_PRIVATE (event_logger); event_logger->priv->event_queue = g_async_queue_new (); } static void ck_event_logger_finalize (GObject *object) { CkEventLogger *event_logger; g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_EVENT_LOGGER (object)); event_logger = CK_EVENT_LOGGER (object); g_return_if_fail (event_logger->priv != NULL); destroy_writer_thread (event_logger); if (event_logger->priv->event_queue != NULL) { g_async_queue_unref (event_logger->priv->event_queue); } if (event_logger->priv->file != NULL) { fclose (event_logger->priv->file); } g_free (event_logger->priv->log_filename); G_OBJECT_CLASS (ck_event_logger_parent_class)->finalize (object); } CkEventLogger * ck_event_logger_new (const char *filename) { GObject *object; object = g_object_new (CK_TYPE_EVENT_LOGGER, "log-filename", filename, NULL); return CK_EVENT_LOGGER (object); } consolekit2-1.2.6/src/ck-event-logger.h000066400000000000000000000046641446640754400177350ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_EVENT_LOGGER_H #define __CK_EVENT_LOGGER_H #include #include "ck-log-event.h" G_BEGIN_DECLS #define CK_TYPE_EVENT_LOGGER (ck_event_logger_get_type ()) #define CK_EVENT_LOGGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_EVENT_LOGGER, CkEventLogger)) #define CK_EVENT_LOGGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_EVENT_LOGGER, CkEventLoggerClass)) #define CK_IS_EVENT_LOGGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_EVENT_LOGGER)) #define CK_IS_EVENT_LOGGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_EVENT_LOGGER)) #define CK_EVENT_LOGGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_EVENT_LOGGER, CkEventLoggerClass)) typedef struct CkEventLoggerPrivate CkEventLoggerPrivate; typedef struct { GObject parent; CkEventLoggerPrivate *priv; } CkEventLogger; typedef struct { GObjectClass parent_class; } CkEventLoggerClass; typedef enum { CK_EVENT_LOGGER_ERROR_GENERAL } CkEventLoggerError; #define CK_EVENT_LOGGER_ERROR ck_event_logger_error_quark () GQuark ck_event_logger_error_quark (void); GType ck_event_logger_get_type (void); CkEventLogger * ck_event_logger_new (const char *filename); gboolean ck_event_logger_queue_event (CkEventLogger *event_logger, CkLogEvent *event, GError **error); G_END_DECLS #endif /* __CK_EVENT_LOGGER_H */ consolekit2-1.2.6/src/ck-file-monitor-dummy.c000066400000000000000000000062021446640754400210550ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include "ck-file-monitor.h" #define CK_FILE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_FILE_MONITOR, CkFileMonitorPrivate)) struct CkFileMonitorPrivate { gpointer dummy; }; static void ck_file_monitor_finalize (GObject *object); G_DEFINE_TYPE (CkFileMonitor, ck_file_monitor, G_TYPE_OBJECT) static gpointer monitor_object = NULL; GQuark ck_file_monitor_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("ck_file_monitor_error"); } return ret; } guint ck_file_monitor_add_notify (CkFileMonitor *monitor, const char *path, int mask, CkFileMonitorNotifyFunc notify_func, gpointer data) { return 0; } void ck_file_monitor_remove_notify (CkFileMonitor *monitor, guint id) { return; } static void ck_file_monitor_class_init (CkFileMonitorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_file_monitor_finalize; g_type_class_add_private (klass, sizeof (CkFileMonitorPrivate)); } static void ck_file_monitor_init (CkFileMonitor *monitor) { monitor->priv = CK_FILE_MONITOR_GET_PRIVATE (monitor); } static void ck_file_monitor_finalize (GObject *object) { CkFileMonitor *monitor; g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_FILE_MONITOR (object)); monitor = CK_FILE_MONITOR (object); g_return_if_fail (monitor->priv != NULL); G_OBJECT_CLASS (ck_file_monitor_parent_class)->finalize (object); } CkFileMonitor * ck_file_monitor_new (void) { if (monitor_object != NULL) { g_object_ref (monitor_object); } else { monitor_object = g_object_new (CK_TYPE_FILE_MONITOR, NULL); g_object_add_weak_pointer (monitor_object, (gpointer *) &monitor_object); } return CK_FILE_MONITOR (monitor_object); } consolekit2-1.2.6/src/ck-file-monitor-inotify.c000066400000000000000000000534221446640754400214110ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "ck-file-monitor.h" #define CK_FILE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_FILE_MONITOR, CkFileMonitorPrivate)) typedef struct { int wd; char *path; GSList *notifies; } FileInotifyWatch; typedef struct { guint id; int mask; CkFileMonitorNotifyFunc notify_func; gpointer user_data; FileInotifyWatch *watch; } FileMonitorNotify; typedef struct { int wd; CkFileMonitorEvent event; char *path; } FileMonitorEventInfo; #define DEFAULT_NOTIFY_BUFLEN (32 * (sizeof (struct inotify_event) + 16)) #define MAX_NOTIFY_BUFLEN (32 * DEFAULT_NOTIFY_BUFLEN) struct CkFileMonitorPrivate { guint serial; gboolean initialized_inotify; int inotify_fd; guint io_watch; GHashTable *wd_to_watch; GHashTable *path_to_watch; GHashTable *notifies; guint buflen; guchar *buffer; guint events_idle_id; guint remove_idle_id; GQueue *notify_events; GQueue *remove_events; }; enum { PROP_0, }; static void ck_file_monitor_finalize (GObject *object); G_DEFINE_TYPE (CkFileMonitor, ck_file_monitor, G_TYPE_OBJECT) static gpointer monitor_object = NULL; GQuark ck_file_monitor_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("ck_file_monitor_error"); } return ret; } /* most of this is adapted from libgnome-menu */ static int our_event_mask_to_inotify_mask (int our_mask) { int mask; mask = 0; if (our_mask & CK_FILE_MONITOR_EVENT_ACCESS) { mask |= IN_ACCESS; } if (our_mask & CK_FILE_MONITOR_EVENT_CREATE) { mask |= IN_CREATE | IN_MOVED_TO; } if (our_mask & CK_FILE_MONITOR_EVENT_DELETE) { mask |= IN_DELETE | IN_DELETE_SELF | IN_MOVED_FROM | IN_MOVE_SELF; } if (our_mask & CK_FILE_MONITOR_EVENT_CHANGE) { mask |= IN_MODIFY | IN_ATTRIB; } return mask; } static char * imask_to_string (guint32 mask) { GString *out; out = g_string_new (NULL); if (mask & IN_ACCESS) { g_string_append (out, "ACCESS "); } if (mask & IN_MODIFY) { g_string_append (out, "MODIFY "); } if (mask & IN_ATTRIB) { g_string_append (out, "ATTRIB "); } if (mask & IN_CLOSE_WRITE) { g_string_append (out, "CLOSE_WRITE "); } if (mask & IN_CLOSE_NOWRITE) { g_string_append (out, "CLOSE_NOWRITE "); } if (mask & IN_OPEN) { g_string_append (out, "OPEN "); } if (mask & IN_MOVED_FROM) { g_string_append (out, "MOVED_FROM "); } if (mask & IN_MOVED_TO) { g_string_append (out, "MOVED_TO "); } if (mask & IN_DELETE) { g_string_append (out, "DELETE "); } if (mask & IN_CREATE) { g_string_append (out, "CREATE "); } if (mask & IN_DELETE_SELF) { g_string_append (out, "DELETE_SELF "); } if (mask & IN_UNMOUNT) { g_string_append (out, "UNMOUNT "); } if (mask & IN_Q_OVERFLOW) { g_string_append (out, "Q_OVERFLOW "); } if (mask & IN_IGNORED) { g_string_append (out, "IGNORED "); } return g_string_free (out, FALSE); } static FileInotifyWatch * file_monitor_add_watch_for_path (CkFileMonitor *monitor, const char *path, int mask) { FileInotifyWatch *watch; int wd; int imask; char *mask_str; imask = our_event_mask_to_inotify_mask (mask); mask_str = imask_to_string (imask); g_debug ("adding inotify watch %s", mask_str); g_free (mask_str); wd = inotify_add_watch (monitor->priv->inotify_fd, path, IN_MASK_ADD | imask); if (wd < 0) { /* FIXME: remove watch etc */ return NULL; } watch = g_hash_table_lookup (monitor->priv->path_to_watch, path); if (watch == NULL) { watch = g_new0 (FileInotifyWatch, 1); watch->wd = wd; watch->path = g_strdup (path); g_hash_table_insert (monitor->priv->path_to_watch, watch->path, watch); g_hash_table_insert (monitor->priv->wd_to_watch, GINT_TO_POINTER (wd), watch); } return watch; } static void monitor_release_watch (CkFileMonitor *monitor, FileInotifyWatch *watch) { g_slist_free (watch->notifies); watch->notifies = NULL; g_free (watch->path); watch->path = NULL; inotify_rm_watch (monitor->priv->inotify_fd, watch->wd); watch->wd = -1; } static void file_monitor_remove_watch (CkFileMonitor *monitor, FileInotifyWatch *watch) { if (watch->wd == -1) { return; } g_hash_table_remove (monitor->priv->path_to_watch, watch->path); g_hash_table_remove (monitor->priv->wd_to_watch, GINT_TO_POINTER (watch->wd)); monitor_release_watch (monitor, watch); } static gboolean remove_watch_foreach (const char *path, FileInotifyWatch *watch, CkFileMonitor *monitor) { monitor_release_watch (monitor, watch); return TRUE; } static void close_inotify (CkFileMonitor *monitor) { if (! monitor->priv->initialized_inotify) { return; } monitor->priv->initialized_inotify = FALSE; g_hash_table_foreach_remove (monitor->priv->path_to_watch, (GHRFunc) remove_watch_foreach, monitor); monitor->priv->path_to_watch = NULL; if (monitor->priv->wd_to_watch != NULL) { g_hash_table_destroy (monitor->priv->wd_to_watch); } monitor->priv->wd_to_watch = NULL; g_free (monitor->priv->buffer); monitor->priv->buffer = NULL; monitor->priv->buflen = 0; if (monitor->priv->io_watch) { g_source_remove (monitor->priv->io_watch); } monitor->priv->io_watch = 0; if (monitor->priv->inotify_fd > 0) { close (monitor->priv->inotify_fd); } monitor->priv->inotify_fd = 0; } static gboolean emit_events_in_idle (CkFileMonitor *monitor) { FileMonitorEventInfo *event_info; char *path; char *freeme; monitor->priv->events_idle_id = 0; while ((event_info = g_queue_pop_head (monitor->priv->notify_events)) != NULL) { GSList *l; FileInotifyWatch *watch; watch = g_hash_table_lookup (monitor->priv->wd_to_watch, GINT_TO_POINTER (event_info->wd)); if (watch != NULL) { for (l = watch->notifies; l != NULL; l = l->next) { FileMonitorNotify *notify; notify = g_hash_table_lookup (monitor->priv->notifies, GUINT_TO_POINTER (l->data)); if (notify == NULL) { continue; } if (! (notify->mask & event_info->event)) { continue; } if (notify->notify_func) { freeme = NULL; if (event_info->path != NULL) { path = freeme = g_build_filename (watch->path, event_info->path, NULL); } else { path = watch->path; } notify->notify_func (monitor, event_info->event, path, notify->user_data); if (freeme != NULL) { g_free (freeme); } } } } event_info->path = NULL; event_info->event = CK_FILE_MONITOR_EVENT_NONE; g_free (event_info); } return FALSE; } static gboolean emit_removals_in_idle (CkFileMonitor *monitor) { gpointer wd_p; FileInotifyWatch *watch; GSList *l; monitor->priv->remove_idle_id = 0; while ((wd_p = g_queue_pop_head (monitor->priv->remove_events)) != NULL) { watch = g_hash_table_lookup (monitor->priv->wd_to_watch, wd_p); if (watch && watch->wd != -1) { for (l = watch->notifies; l != NULL; l = l->next) { FileMonitorNotify *notify; notify = g_hash_table_lookup (monitor->priv->notifies, GUINT_TO_POINTER (l->data)); if (notify == NULL) { continue; } notify->watch = NULL; } file_monitor_remove_watch (monitor, watch); g_free (watch); } } return FALSE; } static void file_monitor_queue_event (CkFileMonitor *monitor, FileMonitorEventInfo *event_info) { g_queue_push_tail (monitor->priv->notify_events, event_info); if (monitor->priv->events_idle_id == 0) { monitor->priv->events_idle_id = g_idle_add ((GSourceFunc) emit_events_in_idle, monitor); } } static void queue_watch_event (CkFileMonitor *monitor, int wd, CkFileMonitorEvent event, const char *path) { FileMonitorEventInfo *event_info; event_info = g_new0 (FileMonitorEventInfo, 1); event_info->wd = wd; event_info->path = g_strdup (path); event_info->event = event; file_monitor_queue_event (monitor, event_info); } static void queue_remove_event (CkFileMonitor *monitor, int wd) { g_queue_push_tail (monitor->priv->remove_events, GINT_TO_POINTER (wd)); if (monitor->priv->remove_idle_id == 0) { monitor->priv->remove_idle_id = g_idle_add ((GSourceFunc) emit_removals_in_idle, monitor); } } static void handle_inotify_event (CkFileMonitor *monitor, struct inotify_event *ievent) { CkFileMonitorEvent event; const char *path; char *mask_str; if (ievent->len > 0) { path = ievent->name; } else { path = NULL; } mask_str = imask_to_string (ievent->mask); g_debug ("handing inotify event %s for %s", mask_str, path); g_free (mask_str); event = CK_FILE_MONITOR_EVENT_NONE; if (ievent->mask & (IN_CREATE | IN_MOVED_TO)) { event = CK_FILE_MONITOR_EVENT_CREATE; } else if (ievent->mask & (IN_DELETE | IN_DELETE_SELF | IN_MOVED_FROM | IN_MOVE_SELF)) { event = CK_FILE_MONITOR_EVENT_DELETE; } else if (ievent->mask & (IN_MODIFY | IN_ATTRIB)) { event = CK_FILE_MONITOR_EVENT_CHANGE; } else if (ievent->mask & IN_ACCESS) { event = CK_FILE_MONITOR_EVENT_ACCESS; } if (event != CK_FILE_MONITOR_EVENT_NONE) { queue_watch_event (monitor, ievent->wd, event, path); } if (ievent->mask & IN_IGNORED) { queue_remove_event (monitor, ievent->wd); } } static gboolean inotify_data_pending (GIOChannel *source, GIOCondition condition, CkFileMonitor *monitor) { int len; int i; g_debug ("Inotify data pending"); g_assert (monitor->priv->inotify_fd > 0); g_assert (monitor->priv->buffer != NULL); do { while ((len = read (monitor->priv->inotify_fd, monitor->priv->buffer, monitor->priv->buflen)) < 0 && errno == EINTR); if (len > 0) { break; } else if (len < 0) { g_warning ("Error reading inotify event: %s", g_strerror (errno)); goto error_cancel; } g_assert (len == 0); if ((monitor->priv->buflen << 1) > MAX_NOTIFY_BUFLEN) { g_warning ("Error reading inotify event: Exceded maximum buffer size"); goto error_cancel; } g_debug ("Buffer size %u too small, trying again at %u\n", monitor->priv->buflen, monitor->priv->buflen << 1); monitor->priv->buflen <<= 1; monitor->priv->buffer = g_realloc (monitor->priv->buffer, monitor->priv->buflen); } while (TRUE); g_debug ("Inotify buffer filled"); i = 0; while (i < len) { struct inotify_event *ievent = (struct inotify_event *) &monitor->priv->buffer [i]; FileInotifyWatch *watch; g_debug ("Got event wd = %d, mask = 0x%x, cookie = %d, len = %d, name= %s\n", ievent->wd, ievent->mask, ievent->cookie, ievent->len, ievent->len > 0 ? ievent->name : ""); watch = g_hash_table_lookup (monitor->priv->wd_to_watch, GINT_TO_POINTER (ievent->wd)); if (watch != NULL) { handle_inotify_event (monitor, ievent); } i += sizeof (struct inotify_event) + ievent->len; } return TRUE; error_cancel: monitor->priv->io_watch = 0; close_inotify (monitor); return FALSE; } static FileMonitorNotify * file_monitor_add_notify_for_path (CkFileMonitor *monitor, const char *path, int mask, CkFileMonitorNotifyFunc notify_func, gpointer data) { FileMonitorNotify *notify; FileInotifyWatch *watch; notify = NULL; watch = file_monitor_add_watch_for_path (monitor, path, mask); if (watch != NULL) { notify = g_new0 (FileMonitorNotify, 1); notify->notify_func = notify_func; notify->user_data = data; notify->id = monitor->priv->serial++; notify->watch = watch; notify->mask = mask; g_debug ("Adding notify for %s mask:%d", path, mask); g_hash_table_insert (monitor->priv->notifies, GUINT_TO_POINTER (notify->id), notify); watch->notifies = g_slist_prepend (watch->notifies, GUINT_TO_POINTER (notify->id)); } return notify; } static void file_monitor_remove_notify (CkFileMonitor *monitor, guint id) { FileMonitorNotify *notify; g_debug ("removing notify for %u", id); notify = g_hash_table_lookup (monitor->priv->notifies, GUINT_TO_POINTER (id)); if (notify == NULL) { return; } g_hash_table_steal (monitor->priv->notifies, GUINT_TO_POINTER (id)); if (notify->watch) { notify->watch->notifies = g_slist_remove (notify->watch->notifies, GUINT_TO_POINTER (id)); if (g_slist_length (notify->watch->notifies) == 0) { file_monitor_remove_watch (monitor, notify->watch); g_free (notify->watch); } } g_free (notify); } guint ck_file_monitor_add_notify (CkFileMonitor *monitor, const char *path, int mask, CkFileMonitorNotifyFunc notify_func, gpointer data) { FileMonitorNotify *notify; if (! monitor->priv->initialized_inotify) { return 0; } notify = file_monitor_add_notify_for_path (monitor, path, mask, notify_func, data); if (notify == NULL) { g_warning ("Failed to add monitor on '%s': %s", path, g_strerror (errno)); return 0; } return notify->id; } void ck_file_monitor_remove_notify (CkFileMonitor *monitor, guint id) { if (! monitor->priv->initialized_inotify) { return; } file_monitor_remove_notify (monitor, id); } static void ck_file_monitor_class_init (CkFileMonitorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_file_monitor_finalize; g_type_class_add_private (klass, sizeof (CkFileMonitorPrivate)); } static void setup_inotify (CkFileMonitor *monitor) { GIOChannel *io_channel; int fd; if (monitor->priv->initialized_inotify) { return; } if ((fd = inotify_init ()) < 0) { g_warning ("Failed to initialize inotify: %s", g_strerror (errno)); return; } monitor->priv->inotify_fd = fd; io_channel = g_io_channel_unix_new (fd); monitor->priv->io_watch = g_io_add_watch (io_channel, G_IO_IN|G_IO_PRI, (GIOFunc) inotify_data_pending, monitor); g_io_channel_unref (io_channel); monitor->priv->buflen = DEFAULT_NOTIFY_BUFLEN; monitor->priv->buffer = g_malloc (DEFAULT_NOTIFY_BUFLEN); monitor->priv->notifies = g_hash_table_new (g_direct_hash, g_direct_equal); monitor->priv->wd_to_watch = g_hash_table_new (g_direct_hash, g_direct_equal); monitor->priv->path_to_watch = g_hash_table_new (g_str_hash, g_str_equal); monitor->priv->initialized_inotify = TRUE; } static void ck_file_monitor_init (CkFileMonitor *monitor) { monitor->priv = CK_FILE_MONITOR_GET_PRIVATE (monitor); monitor->priv->serial = 1; monitor->priv->notify_events = g_queue_new (); monitor->priv->remove_events = g_queue_new (); setup_inotify (monitor); } static void ck_file_monitor_finalize (GObject *object) { CkFileMonitor *monitor; g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_FILE_MONITOR (object)); monitor = CK_FILE_MONITOR (object); g_return_if_fail (monitor->priv != NULL); close_inotify (monitor); g_hash_table_destroy (monitor->priv->notifies); g_queue_free (monitor->priv->notify_events); g_queue_free (monitor->priv->remove_events); G_OBJECT_CLASS (ck_file_monitor_parent_class)->finalize (object); } CkFileMonitor * ck_file_monitor_new (void) { if (monitor_object != NULL) { g_object_ref (monitor_object); } else { monitor_object = g_object_new (CK_TYPE_FILE_MONITOR, NULL); g_object_add_weak_pointer (monitor_object, (gpointer *) &monitor_object); } return CK_FILE_MONITOR (monitor_object); } consolekit2-1.2.6/src/ck-file-monitor.h000066400000000000000000000064461446640754400177430ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_FILE_MONITOR_H #define __CK_FILE_MONITOR_H #include G_BEGIN_DECLS #define CK_TYPE_FILE_MONITOR (ck_file_monitor_get_type ()) #define CK_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_FILE_MONITOR, CkFileMonitor)) #define CK_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_FILE_MONITOR, CkFileMonitorClass)) #define CK_IS_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_FILE_MONITOR)) #define CK_IS_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_FILE_MONITOR)) #define CK_FILE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_FILE_MONITOR, CkFileMonitorClass)) typedef struct CkFileMonitorPrivate CkFileMonitorPrivate; typedef struct { GObject parent; CkFileMonitorPrivate *priv; } CkFileMonitor; typedef struct { GObjectClass parent_class; } CkFileMonitorClass; typedef enum { CK_FILE_MONITOR_EVENT_NONE = 1 << 0, CK_FILE_MONITOR_EVENT_ACCESS = 1 << 1, CK_FILE_MONITOR_EVENT_CREATE = 1 << 2, CK_FILE_MONITOR_EVENT_DELETE = 1 << 3, CK_FILE_MONITOR_EVENT_CHANGE = 1 << 4, } CkFileMonitorEvent; typedef enum { CK_FILE_MONITOR_ERROR_GENERAL } CkFileMonitorError; #define CK_FILE_MONITOR_ERROR ck_file_monitor_error_quark () typedef void (*CkFileMonitorNotifyFunc) (CkFileMonitor *monitor, CkFileMonitorEvent event, const char *path, gpointer user_data); GQuark ck_file_monitor_error_quark (void); GType ck_file_monitor_get_type (void); CkFileMonitor * ck_file_monitor_new (void); guint ck_file_monitor_add_notify (CkFileMonitor *monitor, const char *path, int mask, CkFileMonitorNotifyFunc notify_func, gpointer data); void ck_file_monitor_remove_notify (CkFileMonitor *monitor, guint id); G_END_DECLS #endif /* __CK_FILE_MONITOR_H */ consolekit2-1.2.6/src/ck-inhibit-manager.c000066400000000000000000000365401446640754400203660ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "ck-inhibit.h" #include "ck-inhibit-manager.h" #include "ck-marshal.h" /* For TRACE */ #include "ck-sysdeps.h" #define CK_INHIBIT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_INHIBIT_MANAGER, CkInhibitManagerPrivate)) struct CkInhibitManagerPrivate { /* We could use something more complicated but * it's doubtful there will be more than a dozen items in the list. */ GList *inhibit_list; /* inhibitors is an 2-dimensional array of which events to suppress * and how they are suppressed. * The CkInhibitEvent value is used to indicate how many different * inhibits are suppressing that event. The CkInhibitMode indicates * if it's a block or delay event */ gint inhibitors[CK_INHIBIT_MODE_LAST][CK_INHIBIT_EVENT_LAST]; }; typedef enum { SIG_CHANGED_EVENT, SIG_N_SIGNALS, } INHIBIT_SIGNALS; static guint __signals[SIG_N_SIGNALS] = { 0, }; static void ck_inhibit_manager_finalize (GObject *object); G_DEFINE_TYPE (CkInhibitManager, ck_inhibit_manager, G_TYPE_OBJECT) static void ck_inhibit_manager_class_init (CkInhibitManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_inhibit_manager_finalize; g_type_class_add_private (klass, sizeof (CkInhibitManagerPrivate)); __signals[SIG_CHANGED_EVENT] = g_signal_new("changed-event", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkInhibitManagerClass, changed_event), NULL, NULL, ck_marshal_VOID__INT_INT_BOOLEAN, G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_BOOLEAN); } static void ck_inhibit_manager_init (CkInhibitManager *manager) { manager->priv = CK_INHIBIT_MANAGER_GET_PRIVATE (manager); } static void ck_inhibit_manager_finalize (GObject *object) { G_OBJECT_CLASS (ck_inhibit_manager_parent_class)->finalize (object); } static void cb_changed_event (CkInhibit *inhibit, gint inhibit_mode, gint event, gboolean enabled, gpointer user_data) { CkInhibitManager *manager; CkInhibitManagerPrivate *priv; TRACE (); g_return_if_fail (CK_IS_INHIBIT_MANAGER (user_data)); manager = CK_INHIBIT_MANAGER (user_data); priv = CK_INHIBIT_MANAGER_GET_PRIVATE (manager); if (event < 0 || event >= CK_INHIBIT_EVENT_LAST) { g_warning ("invalid event id"); return; } if (enabled) { priv->inhibitors[inhibit_mode][event]++; if (priv->inhibitors[inhibit_mode][event] == 1) { /* event is now inhibited, send a notification */ g_debug ("event %d is inhibited, emitting signal", event); g_signal_emit(G_OBJECT (manager), __signals[SIG_CHANGED_EVENT], 0, inhibit_mode, event, TRUE); } } else { priv->inhibitors[inhibit_mode][event]--; if (priv->inhibitors[inhibit_mode][event] < 0) { g_warning ("cb_changed_event: priv->inhibitors[%d][%d] " "is negative, that's not supposed to happen", inhibit_mode, event); } if (priv->inhibitors[inhibit_mode][event] == 0) { /* event is no longer inhibited, send a notification */ g_debug ("event %d is no longer inhibited, emitting signal", event); g_signal_emit(G_OBJECT (manager), __signals[SIG_CHANGED_EVENT], 0, inhibit_mode, event, FALSE); } /* When an inhibitor loses it lockes, remove the inhibitor from * the list */ ck_inhibit_manager_remove_lock (manager, ck_inhibit_get_named_pipe_path (inhibit)); } } /** * ck_inhibit_manager_create_lock: * @manager: The @CkInhibitManager object * @who: A human-readable, descriptive string of who is taking * the lock. Example: "Xfburn" * @what: What is a colon-separated list of lock types. * The list of lock types are: shutdown, sleep, idle, * handle-power-key, handle-suspend-key, handle-hibernate-key. * Example: "shutdown:idle" * @why: A human-readable, descriptive string of why the program * is taking the lock. Example: "Burning a DVD, interrupting now * will ruin the DVD." * @mode: Must either be block or delay. block prevents the operation * from happening and will cause a call to perform that action * to fail. delay temporarly prevents the operation from happening * until either the lock is released or a timeout is reached. * @uid: user id. * @pid: process id. * * Initializes an inhibit lock with the supplied paramters and returns * the named pipe. An application can only hold one lock at a time, multiple * calls will fail. * * Return value: The named pipe (a file descriptor) on success. * This is a value of 0 or greater. * Returns a CkInhbitError on failure. **/ gint ck_inhibit_manager_create_lock (CkInhibitManager *manager, const gchar *who, const gchar *what, const gchar *why, const gchar *mode, uid_t uid, pid_t pid) { CkInhibitManagerPrivate *priv; CkInhibit *inhibit; gint fd, signal_id; TRACE (); g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), CK_INHIBIT_ERROR_GENERAL); priv = CK_INHIBIT_MANAGER_GET_PRIVATE (manager); inhibit = ck_inhibit_new (); if (inhibit == NULL) { g_error ("error creating new inhibit object"); return CK_INHIBIT_ERROR_OOM; } /* add our signal handler before we create the lock so we get * the inhibit enable signals. */ signal_id = g_signal_connect (inhibit, "changed-event", G_CALLBACK (cb_changed_event), manager); fd = ck_inhibit_create_lock (inhibit, who, what, why, mode, uid, pid); if (fd == -1) { g_error ("error creating inhibit lock"); /* ensure we disconnect the signal handler and * unref the inhibit object we won't be using */ g_signal_handler_disconnect (inhibit, signal_id); g_object_unref (inhibit); return CK_INHIBIT_ERROR_GENERAL; } /* Add it to our list */ priv->inhibit_list = g_list_append (priv->inhibit_list, inhibit); return fd; } /** * ck_inhibit_manager_remove_lock: * @manager: The @CkInhibitManager object * @named_pipe_path: The unique named pipe path to lock on. * * Finds the inhibit lock @who and removes it. * * Return value: TRUE on successful removal. **/ gboolean ck_inhibit_manager_remove_lock (CkInhibitManager *manager, const gchar *named_pipe_path) { CkInhibitManagerPrivate *priv; GList *l; TRACE (); g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); priv = CK_INHIBIT_MANAGER_GET_PRIVATE (manager); for (l = g_list_first (priv->inhibit_list); l != NULL; l = l->next) { if (l->data && g_strcmp0 (ck_inhibit_get_named_pipe_path (l->data), named_pipe_path) == 0) { /* Found it! Remove it from the list */ ck_inhibit_remove_lock (l->data); g_signal_handlers_disconnect_by_func (l->data, G_CALLBACK (cb_changed_event), manager); priv->inhibit_list = g_list_remove (priv->inhibit_list, l->data); return TRUE; } } return FALSE; } /** * ck_inhibit_manager_get: * * Increases the reference count of the @CkInhibitManager object. * * Return value: Returns a reference to the CkInhibitManager object or * NULL on failure. **/ CkInhibitManager* ck_inhibit_manager_get (void) { static GObject *manager = NULL; if (manager != NULL) { g_object_ref (manager); } else { manager = g_object_new (CK_TYPE_INHIBIT_MANAGER, NULL); g_object_add_weak_pointer (manager, (gpointer *) &manager); } return CK_INHIBIT_MANAGER (manager); } static gboolean get_inhibit_status (CkInhibitManager *manager, CkInhibitEvent event, CkInhibitMode mode) { g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), FALSE); return manager->priv->inhibitors[mode][event] > 0 ? TRUE : FALSE; } /** * ck_inhibit_manager_is_shutdown_delayed: * @manager: The @CkInhibitManager object * * Return value: TRUE is delayed. **/ gboolean ck_inhibit_manager_is_shutdown_delayed (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_SHUTDOWN, CK_INHIBIT_MODE_DELAY); } /** * ck_inhibit_manager_is_shutdown_blocked: * @manager: The @CkInhibitManager object * * Return value: TRUE is blocked. **/ gboolean ck_inhibit_manager_is_shutdown_blocked (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_SHUTDOWN, CK_INHIBIT_MODE_BLOCK); } /** * ck_inhibit_manager_is_suspend_delayed: * @manager: The @CkInhibitManager object * * Return value: TRUE is delayed. **/ gboolean ck_inhibit_manager_is_suspend_delayed (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND, CK_INHIBIT_MODE_DELAY); } /** * ck_inhibit_manager_is_suspend_blocked: * @manager: The @CkInhibitManager object * * Return value: TRUE is blocked. **/ gboolean ck_inhibit_manager_is_suspend_blocked (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND, CK_INHIBIT_MODE_BLOCK); } /** * ck_inhibit_manager_is_idle_delayed: * @manager: The @CkInhibitManager object * * Return value: TRUE is delayed. **/ gboolean ck_inhibit_manager_is_idle_delayed (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_IDLE, CK_INHIBIT_MODE_DELAY); } /** * ck_inhibit_manager_is_idle_blocked: * @manager: The @CkInhibitManager object * * Return value: TRUE is blocked. **/ gboolean ck_inhibit_manager_is_idle_blocked (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_IDLE, CK_INHIBIT_MODE_BLOCK); } /** * ck_inhibit_manager_is_power_key_delayed: * @manager: The @CkInhibitManager object * * Return value: TRUE is delayed. **/ gboolean ck_inhibit_manager_is_power_key_delayed (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_POWER_KEY, CK_INHIBIT_MODE_DELAY); } /** * ck_inhibit_manager_is_power_key_blocked: * @manager: The @CkInhibitManager object * * Return value: TRUE is blocked. **/ gboolean ck_inhibit_manager_is_power_key_blocked (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_POWER_KEY, CK_INHIBIT_MODE_BLOCK); } /** * ck_inhibit_manager_is_suspend_key_delayed: * @manager: The @CkInhibitManager object * * Return value: TRUE is delayed. **/ gboolean ck_inhibit_manager_is_suspend_key_delayed (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND_KEY, CK_INHIBIT_MODE_DELAY); } /** * ck_inhibit_manager_is_suspend_key_blocked: * @manager: The @CkInhibitManager object * * Return value: TRUE is blocked. **/ gboolean ck_inhibit_manager_is_suspend_key_blocked (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_SUSPEND_KEY, CK_INHIBIT_MODE_BLOCK); } /** * ck_inhibit_manager_is_hibernate_key_delayed: * @manager: The @CkInhibitManager object * * Return value: TRUE is delayed. **/ gboolean ck_inhibit_manager_is_hibernate_key_delayed (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_HIBERNATE_KEY, CK_INHIBIT_MODE_DELAY); } /** * ck_inhibit_manager_is_hibernate_key_blocked: * @manager: The @CkInhibitManager object * * Return value: TRUE is blocked. **/ gboolean ck_inhibit_manager_is_hibernate_key_blocked (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_HIBERNATE_KEY, CK_INHIBIT_MODE_BLOCK); } /** * ck_inhibit_manager_is_lid_switch_delayed: * @manager: The @CkInhibitManager object * * Return value: TRUE is delayed. **/ gboolean ck_inhibit_manager_is_lid_switch_delayed (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_LID_SWITCH, CK_INHIBIT_MODE_DELAY); } /** * ck_inhibit_manager_is_lid_switch_blocked: * @manager: The @CkInhibitManager object * * Return value: TRUE is blocked. **/ gboolean ck_inhibit_manager_is_lid_switch_blocked (CkInhibitManager *manager) { return get_inhibit_status (manager, CK_INHIBIT_EVENT_LID_SWITCH, CK_INHIBIT_MODE_BLOCK); } /** * ck_inhibit_manager_get_inhibit_list: * @manager: The @CkInhibitManager object * * Return value: The internal inhibit list. Needed for ck-manager to return * the list of inhibitors. NULL if there's no inhibitors. **/ GList* ck_inhibit_manager_get_inhibit_list (CkInhibitManager *manager) { g_return_val_if_fail (CK_IS_INHIBIT_MANAGER (manager), NULL); return manager->priv->inhibit_list; } consolekit2-1.2.6/src/ck-inhibit-manager.h000066400000000000000000000105051446640754400203640ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_INHIBIT_MANAGER_H #define __CK_INHIBIT_MANAGER_H #include G_BEGIN_DECLS #define CK_TYPE_INHIBIT_MANAGER (ck_inhibit_manager_get_type ()) #define CK_INHIBIT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_INHIBIT_MANAGER, CkInhibitManager)) #define CK_INHIBIT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_INHIBIT_MANAGER, CkInhibitManagerClass)) #define CK_IS_INHIBIT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_INHIBIT_MANAGER)) #define CK_IS_INHIBIT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_INHIBIT_MANAGER)) #define CK_INHIBIT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_INHIBIT_MANAGER, CkInhibitManagerClass)) typedef struct CkInhibitManagerPrivate CkInhibitManagerPrivate; typedef struct { GObject parent; CkInhibitManagerPrivate *priv; } CkInhibitManager; typedef struct { GObjectClass parent_class; /*< signals >*/ void (*changed_event) (CkInhibitManager *manager, gint inhibit_mode, gint event, gboolean enabled); } CkInhibitManagerClass; GType ck_inhibit_manager_get_type (void); CkInhibitManager *ck_inhibit_manager_get (void); gint ck_inhibit_manager_create_lock (CkInhibitManager *manager, const gchar *who, const gchar *what, const gchar *why, const gchar *mode, uid_t uid, pid_t pid); gboolean ck_inhibit_manager_remove_lock (CkInhibitManager *manager, const gchar *named_pipe_path); gboolean ck_inhibit_manager_is_shutdown_delayed (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_suspend_delayed (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_idle_delayed (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_power_key_delayed (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_suspend_key_delayed (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_hibernate_key_delayed (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_lid_switch_delayed (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_shutdown_blocked (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_suspend_blocked (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_idle_blocked (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_power_key_blocked (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_suspend_key_blocked (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_hibernate_key_blocked (CkInhibitManager *manager); gboolean ck_inhibit_manager_is_lid_switch_blocked (CkInhibitManager *manager); GList *ck_inhibit_manager_get_inhibit_list (CkInhibitManager *manager); G_END_DECLS #endif /* __CK_INHIBIT_MANAGER_H */ consolekit2-1.2.6/src/ck-inhibit.c000066400000000000000000000701231446640754400167510ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include "ck-inhibit.h" #include "ck-marshal.h" #define CK_INHIBIT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_INHIBIT, CkInhibitPrivate)) struct CkInhibitPrivate { /* * Who is a human-readable, descriptive string of who is taking * the lock. Example: "Xfburn" */ gchar *who; /* inhibitors is an array of which events to suppress. * Setting an CkInhibitEvent value inside the array to TRUE * marks it for suppression. */ gboolean inhibitors[CK_INHIBIT_EVENT_LAST]; /* * Why is a human-readable, descriptive string of why the program * is taking the lock. Example: "Burning a DVD, interrupting now * will ruin the DVD." */ gchar *why; /* * Mode is the CkInhibitMode, block or delay */ CkInhibitMode mode; /* the uid and pid, used for list inhibitors */ uid_t uid; pid_t pid; /* * named_pipe is a named pipe that the user app will hold onto * while they want the lock to be held. When they close all * references to the named pipe then the lock is released and * this object can be destroyed. */ gint named_pipe; /* named_pipe_path is the location the named pipe is created from */ gchar *named_pipe_path; /* fd_source is the event source id for the g_unix_fd_add call */ gint fd_source; }; typedef enum { SIG_CHANGED_EVENT, SIG_N_SIGNALS, } INHIBIT_SIGNALS; static guint __signals[SIG_N_SIGNALS] = { 0, }; static void ck_inhibit_finalize (GObject *object); static void close_named_pipe (CkInhibit *inhibit); G_DEFINE_TYPE (CkInhibit, ck_inhibit, G_TYPE_OBJECT) static void ck_inhibit_class_init (CkInhibitClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_inhibit_finalize; g_type_class_add_private (klass, sizeof (CkInhibitPrivate)); __signals[SIG_CHANGED_EVENT] = g_signal_new("changed-event", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkInhibitClass, changed_event), NULL, NULL, ck_marshal_VOID__INT_INT_BOOLEAN, G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_BOOLEAN); } static void ck_inhibit_init (CkInhibit *inhibit) { inhibit->priv = CK_INHIBIT_GET_PRIVATE (inhibit); inhibit->priv->named_pipe = -1; } static void ck_inhibit_finalize (GObject *object) { CkInhibit *inhibit; CkInhibitPrivate *priv; g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_INHIBIT (object)); inhibit = CK_INHIBIT (object); g_return_if_fail (inhibit->priv != NULL); priv = CK_INHIBIT_GET_PRIVATE (inhibit); if (priv->fd_source != 0) { g_source_remove (priv->fd_source); priv->fd_source = 0; } close_named_pipe (inhibit); if(inhibit->priv->who != NULL) { g_free (inhibit->priv->who); inhibit->priv->who = NULL; } if(inhibit->priv->why != NULL) { g_free (inhibit->priv->why); inhibit->priv->why = NULL; } G_OBJECT_CLASS (ck_inhibit_parent_class)->finalize (object); } /** * ck_inhibit_new: * * Creates a new CkInhibit object. * * Return value: A @CkInhibit object or NULL on failure. **/ CkInhibit* ck_inhibit_new (void) { GObject *object; object = g_object_new (CK_TYPE_INHIBIT, NULL); if (object == NULL) { return NULL; } return CK_INHIBIT (object); } /* Parses what for the inhibitors to assign to inhibit, invalid options * generate a warning but the operation continues. If at least one * inhibitor was set then it returns TRUE. */ static gboolean parse_inhibitors_string (CkInhibit *inhibit, const gchar *what) { CkInhibitPrivate *priv; gchar **tokens; gint i; gboolean inhibit_set = FALSE; g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); priv = CK_INHIBIT_GET_PRIVATE (inhibit); tokens = g_strsplit (what, ":", 0); /* This rather dense block just parses all the tokens and sets the * inhibit flags*/ for (i = 0; tokens[i] && g_strcmp0 ("", tokens[i]); i++) { if (g_strcmp0 (tokens[i], "shutdown") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN] = TRUE; inhibit_set = TRUE; } else if (g_strcmp0 (tokens[i], "sleep") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND] = TRUE; inhibit_set = TRUE; } else if (g_strcmp0 (tokens[i], "idle") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_IDLE] = TRUE; inhibit_set = TRUE; } else if (g_strcmp0 (tokens[i], "handle-power-key") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY] = TRUE; inhibit_set = TRUE; } else if (g_strcmp0 (tokens[i], "handle-suspend-key") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY] = TRUE; inhibit_set = TRUE; } else if (g_strcmp0 (tokens[i], "handle-hibernate-key") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY] = TRUE; inhibit_set = TRUE; } else if (g_strcmp0 (tokens[i], "handle-lid-switch") == 0) { priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH] = TRUE; inhibit_set = TRUE; } else { g_warning ("requested inhibit operation not supported %s", tokens[i]); } } g_strfreev (tokens); return inhibit_set; } /* Parses what for the inhibitors to assign to inhibit, invalid options * generate a warning but the operation continues. If at least one * inhibitor was set then it returns TRUE. */ static gboolean parse_mode_string (CkInhibit *inhibit, const gchar *mode) { CkInhibitPrivate *priv; g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); priv = CK_INHIBIT_GET_PRIVATE (inhibit); /* Check for whatever inhibit modes we support */ if (g_strcmp0 (mode, "block") == 0) { priv->mode = CK_INHIBIT_MODE_BLOCK; } else if (g_strcmp0 (mode, "delay") == 0) { priv->mode = CK_INHIBIT_MODE_DELAY; } else { return FALSE; } return TRUE; } /* * Creates the /run/ConsoleKit/inhibit directory. The * state_files will exist inside this directory. * Returns TRUE on success. */ static gboolean create_inhibit_base_directory (void) { gint res; errno = 0; res = g_mkdir_with_parents (RUNDIR "/ConsoleKit/inhibit", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (res < 0) { g_warning ("Unable to create directory %s (%s)", RUNDIR "/ConsoleKit/inhibit", g_strerror (errno)); return FALSE; } if (g_chmod (RUNDIR "/ConsoleKit/inhibit", 0755) == -1) { g_warning ("Failed to change permissions for %s", RUNDIR "/ConsoleKit/inhibit"); } return TRUE; } /* When the named pipe is created we then send off the inhibit events */ static void emit_initial_inhibit_signals (CkInhibit *inhibit) { CkInhibitPrivate *priv; g_return_if_fail (CK_IS_INHIBIT (inhibit)); /* keep a ref to ourselves so we don't get destroyed before * all the messages are sent. Probably not going to happen * during the initial inhibit signals but better to be safe. */ g_object_ref (inhibit); priv = CK_INHIBIT_GET_PRIVATE (inhibit); if (priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN]) { g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SHUTDOWN, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND]) { g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_IDLE]) { g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_IDLE, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY]) { g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_POWER_KEY, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY]) { g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND_KEY, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY]) { g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_HIBERNATE_KEY, TRUE); } if (priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH]) { g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_LID_SWITCH, TRUE); } g_object_unref (inhibit); } /* When the named pipe is closed we set them to FALSE and send off the * uninhibit events */ static void emit_final_uninhibit_signals (CkInhibit *inhibit) { CkInhibitPrivate *priv; if (inhibit == NULL || !CK_IS_INHIBIT (inhibit)) { return; } priv = CK_INHIBIT_GET_PRIVATE (inhibit); if (CK_IS_INHIBIT (inhibit) && priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN]) { priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN] = FALSE; g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SHUTDOWN, FALSE); } if (CK_IS_INHIBIT (inhibit) && priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND]) { priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND] = FALSE; g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND, FALSE); } if (CK_IS_INHIBIT (inhibit) && priv->inhibitors[CK_INHIBIT_EVENT_IDLE]) { priv->inhibitors[CK_INHIBIT_EVENT_IDLE] = FALSE; g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_IDLE, FALSE); } if (CK_IS_INHIBIT (inhibit) && priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY]) { priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY] = FALSE; g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_POWER_KEY, FALSE); } if (CK_IS_INHIBIT (inhibit) && priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY]) { priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY] = FALSE; g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_SUSPEND_KEY, FALSE); } if (CK_IS_INHIBIT (inhibit) && priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY]) { priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY] = FALSE; g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_HIBERNATE_KEY, FALSE); } if (CK_IS_INHIBIT (inhibit) && priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH]) { priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH] = FALSE; g_signal_emit(G_OBJECT (inhibit), __signals[SIG_CHANGED_EVENT], 0, priv->mode, CK_INHIBIT_EVENT_LID_SWITCH, FALSE); } } /* * - Closes the named_pipe if opened. * - Unlinks the named_pipe_path if created. * - Frees the memory allocated to the named_pipe_path. */ static void close_named_pipe (CkInhibit *inhibit) { CkInhibitPrivate *priv; GError *error = NULL; g_return_if_fail (CK_IS_INHIBIT (inhibit)); priv = CK_INHIBIT_GET_PRIVATE (inhibit); if (priv->named_pipe == -1) { return; } else { if (g_close (priv->named_pipe, &error) == -1) { g_warning ("Failed to close inhibit named pipe, error was %s", error->message); g_error_free (error); } priv->named_pipe = -1; } if (priv->named_pipe_path) { if (g_unlink (priv->named_pipe_path) == -1) { g_warning ("Failed to remove inhibit file %s, error reported: %s", priv->named_pipe_path, g_strerror(errno)); } g_free (priv->named_pipe_path); priv->named_pipe_path = NULL; } if (priv->fd_source != 0) { g_source_remove (priv->fd_source); priv->fd_source = 0; } /* let others know we aren't holding any locks anymore */ emit_final_uninhibit_signals (inhibit); } static gboolean cb_named_pipe_close (GIOChannel *source, GIOCondition condition, gpointer user_data) { CkInhibit *inhibit; /* Sanity checks */ if (user_data == NULL) { g_warning ("cb_named_pipe_close: user_data == NULL"); return FALSE; } if (!CK_IS_INHIBIT (user_data)) { g_warning ("cb_named_pipe_close: !CK_IS_INHIBIT (user_data)"); return FALSE; } inhibit = CK_INHIBIT (user_data); /* We're about to return FALSE and close the glib source so reset it */ inhibit->priv->fd_source = 0; close_named_pipe (inhibit); return FALSE; } /* Builds the path to the named pipe. Free the returned string when done. */ static gchar* get_named_pipe_path (void) { char *path; gint tmp_fd; GError *error; errno = 0; path = g_strdup_printf ("%s/ConsoleKit/inhibit/inhibit.XXXXXX.pipe", RUNDIR); /* check that we got a string */ if (path == NULL) { return NULL; } /* make the file unique */ tmp_fd = g_mkstemp (path); /* failed to get unique filename */ if (tmp_fd == -1) { g_warning ("failed to create unique named pipe (%s): %s", path, g_strerror(errno)); g_free (path); return NULL; } if (!g_close (tmp_fd, &error)) { g_warning ("failed to close unique named pipe: %s", error->message); g_error_free (error); return NULL; } return path; } /* * Creates the named pipe. * Returns the fd if successful (return >= 0) or -1 */ static gint create_named_pipe (CkInhibit *inhibit) { CkInhibitPrivate *priv; GIOChannel *io; g_return_val_if_fail (CK_IS_INHIBIT (inhibit), -1); priv = CK_INHIBIT_GET_PRIVATE (inhibit); /* Basic error checking */ if (priv->named_pipe != -1) { g_warning ("Attempting to create an inhibit fd when one already exists"); return -1; } if (priv->named_pipe_path == NULL) { g_warning ("named_pipe_path cannot be NULL"); return -1; } if (g_unlink (priv->named_pipe_path) == -1) { g_warning ("failed to remove temp inhibit file"); return -1; } /* create the named pipe */ errno = 0; if (mknod (priv->named_pipe_path, S_IFIFO | 0600 , 0) == -1) { g_warning ("failed to create named pipe: %s", g_strerror(errno)); return -1; } /* open our side */ priv->named_pipe = g_open (priv->named_pipe_path, O_RDONLY|O_CLOEXEC|O_NDELAY); if (priv->named_pipe < 0) { g_warning ("failed to open the named pipe for reading %s", g_strerror(errno)); return -1; } /* Monitor the named pipe */ io = g_io_channel_unix_new (priv->named_pipe); priv->fd_source = g_io_add_watch (io, G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)cb_named_pipe_close, inhibit); /* open the client side of the named pipe and return it */ return open(priv->named_pipe_path, O_WRONLY|O_CLOEXEC|O_NDELAY); } /** * ck_inhibit_create_lock: * @inhibit: The @CkInhibit object * @who: A human-readable, descriptive string of who is taking * the lock. Example: "Xfburn" * @what: What is a colon-separated list of lock types. * The list of lock types are: shutdown, sleep, idle, * handle-power-key, handle-suspend-key, handle-hibernate-key. * Example: "shutdown:idle" * @why: A human-readable, descriptive string of why the program * is taking the lock. Example: "Burning a DVD, interrupting now * will ruin the DVD." * @mode: Must either be block or delay. block prevents the operation * from happening and will cause a call to perform that action * to fail. delay temporarly prevents the operation from happening * until either the lock is released or a timeout is reached. * @uid: user id. * @pid: process id. * * Initializes the lock fd and populates the inhibit object with data. * * Return value: The named pipe (a file descriptor) on success. * This is a value of 0 or greater. * Returns a CkInhbitError on failure. **/ gint ck_inhibit_create_lock (CkInhibit *inhibit, const gchar *who, const gchar *what, const gchar *why, const gchar *mode, uid_t uid, pid_t pid) { CkInhibitPrivate *priv; gint pipe; g_return_val_if_fail (CK_IS_INHIBIT (inhibit), CK_INHIBIT_ERROR_INVALID_INPUT); /* These fields only get set here and are mandatory */ if (!who || !what || !why || !mode) { g_warning ("who, what, and why and mandatory for inhibit locks"); return CK_INHIBIT_ERROR_INVALID_INPUT; } priv = CK_INHIBIT_GET_PRIVATE (inhibit); /* always make sure we have a directory to work in */ if (create_inhibit_base_directory () == FALSE) { return CK_INHIBIT_ERROR_GENERAL; } /* fill in the inihibt values */ priv->who = g_strdup (who); priv->why = g_strdup (why); priv->uid = uid; priv->pid = pid; priv->named_pipe_path = get_named_pipe_path (); if (!parse_inhibitors_string(inhibit, what)) { g_warning ("Failed to set any inhibitors."); return CK_INHIBIT_ERROR_INVALID_INPUT; } if (!parse_mode_string(inhibit, mode)) { g_warning ("Failed to set inhibit mode."); return CK_INHIBIT_ERROR_INVALID_INPUT; } if(priv->named_pipe_path == NULL) { g_warning ("Failed to allocate memory for inhibit state_file string"); return CK_INHIBIT_ERROR_OOM; } /* create the named pipe and get the fd to return. */ pipe = create_named_pipe (inhibit); if (pipe == -1) { g_warning ("Failed to created named pipe"); return CK_INHIBIT_ERROR_GENERAL; } /* let others know which locks we now hold */ emit_initial_inhibit_signals (inhibit); /* return the fd for the user */ return pipe; } void ck_inhibit_remove_lock (CkInhibit *inhibit) { return close_named_pipe (inhibit); } /* Adds what to the string, frees the old string if needed, and returns the * newly created string */ static gchar* add_item_to_string (gchar *string, const gchar* what) { gchar *temp; /* nothing to do, easy */ if (what == NULL) { return string; } /* start of our string */ if (string == NULL) { return g_strdup (what); } /* add :what to the existing string */ temp = g_strdup_printf ("%s:%s", string, what); g_free (string); return temp; } /* We check if the inhibit event is set, if so we add what to the string * and return a new string. The old string that's passed in is freed if not * needed anymore. */ static gchar* check_event_and_add_to_string (CkInhibit *inhibit, CkInhibitEvent event, const gchar *what, gchar *string) { if (inhibit->priv->inhibitors[event]) { string = add_item_to_string (string, what); } return string; } /** * ck_inhibit_get_what: * @inhibit: The @CkInhibit object * * Return value: A string representation of the things being inhibited. **/ const gchar* ck_inhibit_get_what (CkInhibit *inhibit) { gchar *string = NULL; g_return_val_if_fail (CK_IS_INHIBIT (inhibit), NULL); string = check_event_and_add_to_string (inhibit, CK_INHIBIT_EVENT_SHUTDOWN, "shutdown", string); string = check_event_and_add_to_string (inhibit, CK_INHIBIT_EVENT_SUSPEND, "suspend", string); string = check_event_and_add_to_string (inhibit, CK_INHIBIT_EVENT_IDLE, "idle", string); string = check_event_and_add_to_string (inhibit, CK_INHIBIT_EVENT_POWER_KEY, "handle-power-key", string); string = check_event_and_add_to_string (inhibit, CK_INHIBIT_EVENT_SUSPEND_KEY, "handle-suspend-key", string); string = check_event_and_add_to_string (inhibit, CK_INHIBIT_EVENT_HIBERNATE_KEY, "handle-hibernate-key", string); string = check_event_and_add_to_string (inhibit, CK_INHIBIT_EVENT_LID_SWITCH, "handle-lid-switch", string); return string; } /** * ck_inhibit_get_who: * @inhibit: The @CkInhibit object * * Return value: who initiated the inhibit lock. **/ const gchar* ck_inhibit_get_who (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), NULL); return inhibit->priv->who; } /** * ck_inhibit_get_why: * @inhibit: The @CkInhibit object * * Return value: why it is inhibited. **/ const gchar* ck_inhibit_get_why (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), NULL); return inhibit->priv->why; } /** * ck_inhibit_get_mode: * @inhibit: The @CkInhibit object * * Return value: the inhibit mode, either "delay" or "block" (or NULL on failure). **/ const gchar* ck_inhibit_get_mode (CkInhibit *inhibit) { CkInhibitPrivate *priv; g_return_val_if_fail (CK_IS_INHIBIT (inhibit), NULL); priv = CK_INHIBIT_GET_PRIVATE (inhibit); if (priv->mode == CK_INHIBIT_MODE_BLOCK) { return "block"; } else if (priv->mode == CK_INHIBIT_MODE_DELAY) { return "delay"; } /* if mode wasn't set to block or delay, there was an error */ return NULL; } /** * ck_inhibit_get_named_pipe: * @inhibit: The @CkInhibit object * * Return value: the inhibit mode, either "delay" or "block" (or NULL on failure). **/ const gchar* ck_inhibit_get_named_pipe_path (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), NULL); return inhibit->priv->named_pipe_path; } /** * ck_inhibit_get_uid: * @inhibit: The @CkInhibit object * * Return value: return the uid or 0 on failure. **/ uid_t ck_inhibit_get_uid (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), 0); return inhibit->priv->uid; } /** * ck_inhibit_get_pid: * @inhibit: The @CkInhibit object * * Return value: return the pid or 0 on failure. **/ pid_t ck_inhibit_get_pid (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), 0); return inhibit->priv->pid; } /** * ck_inhibit_get_inhibit_mode: * @inhibit: The @CkInhibit object * * Return value: The CkInhibitMode directly, rather than a string representation. **/ CkInhibitMode ck_inhibit_get_inhibit_mode (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), CK_INHIBIT_MODE_INVALID); return inhibit->priv->mode; } /** * ck_inhibit_is_shutdown_inhibited: * @inhibit: The @CkInhibit object * * Return value: TRUE is inhibited. **/ gboolean ck_inhibit_is_shutdown_inhibited (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_SHUTDOWN]; } /** * ck_inhibit_is_suspend_inhibited: * @inhibit: The @CkInhibit object * * Return value: TRUE is inhibited. **/ gboolean ck_inhibit_is_suspend_inhibited (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND]; } /** * ck_inhibit_is_idle_inhibited: * @inhibit: The @CkInhibit object * * Return value: TRUE is inhibited. **/ gboolean ck_inhibit_is_idle_inhibited (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_IDLE]; } /** * ck_inhibit_is_power_key_inhibited: * @inhibit: The @CkInhibit object * * Return value: TRUE is inhibited. **/ gboolean ck_inhibit_is_power_key_inhibited (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_POWER_KEY]; } /** * ck_inhibit_is_suspend_key_inhibited: * @inhibit: The @CkInhibit object * * Return value: TRUE is inhibited. **/ gboolean ck_inhibit_is_suspend_key_inhibited (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_SUSPEND_KEY]; } /** * ck_inhibit_is_hibernate_key_inhibited: * @inhibit: The @CkInhibit object * * Return value: TRUE is inhibited. **/ gboolean ck_inhibit_is_hibernate_key_inhibited (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_HIBERNATE_KEY]; } /** * ck_inhibit_is_lid_switch_inhibited: * @inhibit: The @CkInhibit object * * Return value: TRUE is inhibited. **/ gboolean ck_inhibit_is_lid_switch_inhibited (CkInhibit *inhibit) { g_return_val_if_fail (CK_IS_INHIBIT (inhibit), FALSE); return inhibit->priv->inhibitors[CK_INHIBIT_EVENT_LID_SWITCH]; } consolekit2-1.2.6/src/ck-inhibit.h000066400000000000000000000111461446640754400167560ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_INHIBIT_H #define __CK_INHIBIT_H #include G_BEGIN_DECLS #define CK_TYPE_INHIBIT (ck_inhibit_get_type ()) #define CK_INHIBIT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_INHIBIT, CkInhibit)) #define CK_INHIBIT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_INHIBIT, CkInhibitClass)) #define CK_IS_INHIBIT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_INHIBIT)) #define CK_IS_INHIBIT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_INHIBIT)) #define CK_INHIBIT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_INHIBIT, CkInhibitClass)) typedef struct CkInhibitPrivate CkInhibitPrivate; typedef struct { GObject parent; CkInhibitPrivate *priv; } CkInhibit; typedef struct { GObjectClass parent_class; /*< signals >*/ void (*changed_event) (CkInhibit *inhibit, gint inhibit_mode, gint event, gboolean enabled); } CkInhibitClass; /* The list of events that may be inhibited -- except for event_last :) */ typedef enum { CK_INHIBIT_EVENT_SHUTDOWN = 0, CK_INHIBIT_EVENT_SUSPEND, CK_INHIBIT_EVENT_IDLE, CK_INHIBIT_EVENT_POWER_KEY, CK_INHIBIT_EVENT_SUSPEND_KEY, CK_INHIBIT_EVENT_HIBERNATE_KEY, CK_INHIBIT_EVENT_LID_SWITCH, CK_INHIBIT_EVENT_LAST } CkInhibitEvent; /* The list of inhibit modes -- except for mode_last and invalid */ typedef enum { CK_INHIBIT_MODE_INVALID = 0, CK_INHIBIT_MODE_BLOCK, CK_INHIBIT_MODE_DELAY, CK_INHIBIT_MODE_LAST } CkInhibitMode; /* * Various error codes for CkInhibit. All the values will be negative except * for NO_ERROR */ typedef enum { CK_INHIBIT_ERROR_NO_ERROR = 1, CK_INHIBIT_ERROR_GENERAL = -10, CK_INHIBIT_ERROR_INVALID_INPUT = -20, CK_INHIBIT_ERROR_OOM = -30, } CkInhbitError; GType ck_inhibit_get_type (void); CkInhibit *ck_inhibit_new (void); gint ck_inhibit_create_lock (CkInhibit *inhibit, const gchar *who, const gchar *what, const gchar *why, const gchar *mode, uid_t uid, pid_t pid); void ck_inhibit_remove_lock (CkInhibit *inhibit); const gchar *ck_inhibit_get_what (CkInhibit *inhibit); const gchar *ck_inhibit_get_who (CkInhibit *inhibit); const gchar *ck_inhibit_get_why (CkInhibit *inhibit); const gchar *ck_inhibit_get_mode (CkInhibit *inhibit); const gchar *ck_inhibit_get_named_pipe_path (CkInhibit *inhibit); CkInhibitMode ck_inhibit_get_inhibit_mode (CkInhibit *inhibit); uid_t ck_inhibit_get_uid (CkInhibit *inhibit); pid_t ck_inhibit_get_pid (CkInhibit *inhibit); gboolean ck_inhibit_is_shutdown_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_suspend_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_idle_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_power_key_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_suspend_key_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_hibernate_key_inhibited (CkInhibit *inhibit); gboolean ck_inhibit_is_lid_switch_inhibited (CkInhibit *inhibit); G_END_DECLS #endif /* __CK_INHIBIT_H */ consolekit2-1.2.6/src/ck-job.c000066400000000000000000000255501446640754400161010ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-job.h" #include "ck-marshal.h" #define CK_JOB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_JOB, CkJobPrivate)) struct CkJobPrivate { guint err_watch_id; guint out_watch_id; char *command; GString *std_out; GString *std_err; GPid child_pid; }; enum { COMPLETED, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0, }; static void ck_job_finalize (GObject *object); G_DEFINE_TYPE (CkJob, ck_job, G_TYPE_OBJECT) GQuark ck_job_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("ck_job_error"); } return ret; } static int wait_on_child (int pid) { int status; wait_again: if (waitpid (pid, &status, 0) < 0) { if (errno == EINTR) { goto wait_again; } else if (errno == ECHILD) { ; /* do nothing, child already reaped */ } else { g_debug ("waitpid () should not fail"); } } return status; } static int wait_on_job (CkJob *job) { int status; status = wait_on_child (job->priv->child_pid); g_spawn_close_pid (job->priv->child_pid); job->priv->child_pid = 0; return WEXITSTATUS(status); } static void maybe_complete_job (CkJob *job) { if (job->priv->out_watch_id == 0 && job->priv->err_watch_id == 0) { int status; status = wait_on_job (job); g_debug ("Emitting completed"); g_signal_emit (job, signals [COMPLETED], 0, status); } } static gboolean error_watch (GIOChannel *source, GIOCondition condition, CkJob *job) { gboolean finished = FALSE; if (condition & G_IO_IN) { GIOStatus status; GError *error = NULL; char *line; line = NULL; status = g_io_channel_read_line (source, &line, NULL, NULL, &error); switch (status) { case G_IO_STATUS_NORMAL: g_debug ("command error output: %s", line); g_string_append (job->priv->std_err, line); break; case G_IO_STATUS_EOF: finished = TRUE; break; case G_IO_STATUS_ERROR: finished = TRUE; g_debug ("Error reading from child: %s\n", error->message); break; case G_IO_STATUS_AGAIN: default: break; } g_free (line); } else if (condition & G_IO_HUP) { finished = TRUE; } if (finished) { job->priv->err_watch_id = 0; maybe_complete_job (job); return FALSE; } return TRUE; } static gboolean out_watch (GIOChannel *source, GIOCondition condition, CkJob *job) { gboolean finished = FALSE; if (condition & G_IO_IN) { GIOStatus status; GError *error = NULL; char *line; line = NULL; status = g_io_channel_read_line (source, &line, NULL, NULL, &error); switch (status) { case G_IO_STATUS_NORMAL: g_string_append (job->priv->std_out, line); break; case G_IO_STATUS_EOF: finished = TRUE; break; case G_IO_STATUS_ERROR: finished = TRUE; g_debug ("Error reading from child: %s\n", error->message); break; case G_IO_STATUS_AGAIN: default: break; } g_free (line); } else if (condition & G_IO_HUP) { finished = TRUE; } if (finished) { job->priv->out_watch_id = 0; maybe_complete_job (job); return FALSE; } return TRUE; } gboolean ck_job_execute (CkJob *job, GError **error) { GError *local_error; gboolean res; GIOChannel *channel; int standard_output; int standard_error; int argc; char **argv; g_debug ("Executing %s", job->priv->command); local_error = NULL; if (! g_shell_parse_argv (job->priv->command, &argc, &argv, &local_error)) { g_debug ("Could not parse command: %s", local_error->message); g_propagate_error (error, local_error); return FALSE; } local_error = NULL; res = g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &job->priv->child_pid, NULL, &standard_output, &standard_error, &local_error); g_strfreev (argv); if (! res) { g_debug ("Could not start command '%s': %s", job->priv->command, local_error->message); g_propagate_error (error, local_error); return FALSE; } /* output channel */ channel = g_io_channel_unix_new (standard_output); g_io_channel_set_close_on_unref (channel, TRUE); g_io_channel_set_flags (channel, g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK, NULL); job->priv->out_watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)out_watch, job); g_io_channel_unref (channel); /* error channel */ channel = g_io_channel_unix_new (standard_error); g_io_channel_set_close_on_unref (channel, TRUE); g_io_channel_set_flags (channel, g_io_channel_get_flags (channel) | G_IO_FLAG_NONBLOCK, NULL); job->priv->err_watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, (GIOFunc)error_watch, job); g_io_channel_unref (channel); return res; } gboolean ck_job_get_stdout (CkJob *job, char **std_outp) { if (std_outp != NULL) { *std_outp = g_strdup (job->priv->std_out->str); } return TRUE; } gboolean ck_job_set_command (CkJob *job, const char *command) { g_free (job->priv->command); job->priv->command = g_strdup (command); return TRUE; } gboolean ck_job_get_command (CkJob *job, char **command) { if (command != NULL) { *command = g_strdup (job->priv->command); } return TRUE; } static void ck_job_class_init (CkJobClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_job_finalize; signals [COMPLETED] = g_signal_new ("completed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkJobClass, completed), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); g_type_class_add_private (klass, sizeof (CkJobPrivate)); } static void ck_job_init (CkJob *job) { job->priv = CK_JOB_GET_PRIVATE (job); job->priv->std_err = g_string_new (NULL); job->priv->std_out = g_string_new (NULL); } gboolean ck_job_cancel (CkJob *job) { if (job->priv->child_pid > 0) { kill (job->priv->child_pid, SIGTERM); wait_on_job (job); return TRUE; } return FALSE; } static void ck_job_finalize (GObject *object) { CkJob *job; g_debug ("Finalizing job"); g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_JOB (object)); job = CK_JOB (object); g_return_if_fail (job->priv != NULL); ck_job_cancel (job); if (job->priv->out_watch_id > 0) { g_source_remove (job->priv->out_watch_id); job->priv->out_watch_id = 0; } if (job->priv->err_watch_id > 0) { g_source_remove (job->priv->err_watch_id); job->priv->err_watch_id = 0; } g_free (job->priv->command); g_string_free (job->priv->std_out, TRUE); g_string_free (job->priv->std_err, TRUE); G_OBJECT_CLASS (ck_job_parent_class)->finalize (object); } CkJob * ck_job_new (void) { GObject *object; object = g_object_new (CK_TYPE_JOB, NULL); return CK_JOB (object); } consolekit2-1.2.6/src/ck-job.h000066400000000000000000000053171446640754400161050ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_JOB_H #define __CK_JOB_H #include G_BEGIN_DECLS #define CK_TYPE_JOB (ck_job_get_type ()) #define CK_JOB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_JOB, CkJob)) #define CK_JOB_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_JOB, CkJobClass)) #define CK_IS_JOB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_JOB)) #define CK_IS_JOB_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_JOB)) #define CK_JOB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_JOB, CkJobClass)) typedef struct CkJobPrivate CkJobPrivate; typedef struct { GObject parent; CkJobPrivate *priv; } CkJob; typedef struct { GObjectClass parent_class; void (* completed) (CkJob *job, int status); } CkJobClass; typedef enum { CK_JOB_ERROR_GENERAL } CkJobError; #define CK_JOB_ERROR ck_job_error_quark () GQuark ck_job_error_quark (void); GType ck_job_get_type (void); CkJob * ck_job_new (void); gboolean ck_job_set_command (CkJob *job, const char *command); gboolean ck_job_get_command (CkJob *job, char **command); gboolean ck_job_execute (CkJob *job, GError **error); gboolean ck_job_get_stdout (CkJob *job, char **std_output); gboolean ck_job_get_stderr (CkJob *job, char **std_error); gboolean ck_job_cancel (CkJob *job); G_END_DECLS #endif /* __CK_JOB_H */ consolekit2-1.2.6/src/ck-log-event.c000066400000000000000000001277721446640754400172400ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include "ck-log-event.h" static void event_seat_added_free (CkLogSeatAddedEvent *event) { g_assert (event != NULL); g_free (event->seat_id); event->seat_id = NULL; } static void event_seat_removed_free (CkLogSeatRemovedEvent *event) { g_assert (event != NULL); g_free (event->seat_id); event->seat_id = NULL; } static void event_system_stop_free (CkLogSystemStopEvent *event) { g_assert (event != NULL); } static void event_system_restart_free (CkLogSystemRestartEvent *event) { g_assert (event != NULL); } static void event_system_start_free (CkLogSystemStartEvent *event) { g_assert (event != NULL); g_free (event->kernel_release); g_free (event->boot_arguments); } static void event_system_suspend_free (CkLogSystemSuspendEvent *event) { g_assert (event != NULL); } static void event_system_hibernate_free (CkLogSystemHibernateEvent *event) { g_assert (event != NULL); } static void event_seat_session_added_free (CkLogSeatSessionAddedEvent *event) { g_assert (event != NULL); g_free (event->seat_id); event->seat_id = NULL; g_free (event->session_id); event->session_id = NULL; g_free (event->session_type); event->session_type = NULL; g_free (event->session_x11_display); event->session_x11_display = NULL; g_free (event->session_x11_display_device); event->session_x11_display_device = NULL; g_free (event->session_display_device); event->session_display_device = NULL; g_free (event->session_remote_host_name); event->session_remote_host_name = NULL; g_free (event->session_creation_time); event->session_creation_time = NULL; } static void event_seat_session_removed_free (CkLogSeatSessionRemovedEvent *event) { g_assert (event != NULL); g_free (event->seat_id); event->seat_id = NULL; g_free (event->session_id); event->session_id = NULL; g_free (event->session_type); event->session_type = NULL; g_free (event->session_x11_display); event->session_x11_display = NULL; g_free (event->session_x11_display_device); event->session_x11_display_device = NULL; g_free (event->session_display_device); event->session_display_device = NULL; g_free (event->session_remote_host_name); event->session_remote_host_name = NULL; g_free (event->session_creation_time); event->session_creation_time = NULL; } static void event_seat_active_session_changed_free (CkLogSeatActiveSessionChangedEvent *event) { g_assert (event != NULL); g_free (event->seat_id); event->seat_id = NULL; g_free (event->session_id); event->session_id = NULL; } static void event_seat_device_added_free (CkLogSeatDeviceAddedEvent *event) { g_assert (event != NULL); g_free (event->seat_id); event->seat_id = NULL; g_free (event->device_id); event->device_id = NULL; g_free (event->device_type); event->device_type = NULL; } static void event_seat_device_removed_free (CkLogSeatDeviceRemovedEvent *event) { g_assert (event != NULL); g_free (event->seat_id); event->seat_id = NULL; g_free (event->device_id); event->device_id = NULL; g_free (event->device_type); event->device_type = NULL; } static void event_seat_added_copy (CkLogSeatAddedEvent *event, CkLogSeatAddedEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->seat_id = g_strdup (event->seat_id); event_copy->seat_kind = event->seat_kind; } static void event_seat_removed_copy (CkLogSeatRemovedEvent *event, CkLogSeatRemovedEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->seat_id = g_strdup (event->seat_id); event_copy->seat_kind = event->seat_kind; } static void event_system_stop_copy (CkLogSystemStopEvent *event, CkLogSystemStopEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); } static void event_system_restart_copy (CkLogSystemRestartEvent *event, CkLogSystemRestartEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); } static void event_system_start_copy (CkLogSystemStartEvent *event, CkLogSystemStartEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->kernel_release = g_strdup (event->kernel_release); event_copy->boot_arguments = g_strdup (event->boot_arguments); } static void event_system_suspend_copy (CkLogSystemSuspendEvent *event, CkLogSystemSuspendEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); } static void event_system_hibernate_copy (CkLogSystemHibernateEvent *event, CkLogSystemHibernateEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); } static void event_seat_session_added_copy (CkLogSeatSessionAddedEvent *event, CkLogSeatSessionAddedEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->seat_id = g_strdup (event->seat_id); event_copy->session_id = g_strdup (event->session_id); event_copy->session_type = g_strdup (event->session_type); event_copy->session_x11_display = g_strdup (event->session_x11_display); event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device); event_copy->session_display_device = g_strdup (event->session_display_device); event_copy->session_remote_host_name = g_strdup (event->session_remote_host_name); event_copy->session_is_local = event->session_is_local; event_copy->session_unix_user = event->session_unix_user; event_copy->session_creation_time = g_strdup (event->session_creation_time); } static void event_seat_session_removed_copy (CkLogSeatSessionRemovedEvent *event, CkLogSeatSessionRemovedEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->seat_id = g_strdup (event->seat_id); event_copy->session_id = g_strdup (event->session_id); event_copy->session_type = g_strdup (event->session_type); event_copy->session_x11_display = g_strdup (event->session_x11_display); event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device); event_copy->session_display_device = g_strdup (event->session_display_device); event_copy->session_remote_host_name = g_strdup (event->session_remote_host_name); event_copy->session_is_local = event->session_is_local; event_copy->session_unix_user = event->session_unix_user; event_copy->session_creation_time = g_strdup (event->session_creation_time); } static void event_seat_active_session_changed_copy (CkLogSeatActiveSessionChangedEvent *event, CkLogSeatActiveSessionChangedEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->seat_id = g_strdup (event->seat_id); event_copy->session_id = g_strdup (event->session_id); } static void event_seat_device_added_copy (CkLogSeatDeviceAddedEvent *event, CkLogSeatDeviceAddedEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->seat_id = g_strdup (event->seat_id); event_copy->device_id = g_strdup (event->device_id); event_copy->device_type = g_strdup (event->device_type); } static void event_seat_device_removed_copy (CkLogSeatDeviceRemovedEvent *event, CkLogSeatDeviceRemovedEvent *event_copy) { g_assert (event != NULL); g_assert (event_copy != NULL); event_copy->seat_id = g_strdup (event->seat_id); event_copy->device_id = g_strdup (event->device_id); event_copy->device_type = g_strdup (event->device_type); } CkLogEvent * ck_log_event_copy (CkLogEvent *event) { CkLogEvent *event_copy; if (event == NULL) { return NULL; } event_copy = g_new0 (CkLogEvent, 1); event_copy->type = event->type; event_copy->timestamp = event->timestamp; switch (event->type) { case CK_LOG_EVENT_SEAT_ADDED: event_seat_added_copy ((CkLogSeatAddedEvent *) event, (CkLogSeatAddedEvent *) event_copy); break; case CK_LOG_EVENT_SEAT_REMOVED: event_seat_removed_copy ((CkLogSeatRemovedEvent *) event, (CkLogSeatRemovedEvent *) event_copy); break; case CK_LOG_EVENT_SYSTEM_STOP: event_system_stop_copy ((CkLogSystemStopEvent *) event, (CkLogSystemStopEvent *) event_copy); break; case CK_LOG_EVENT_SYSTEM_RESTART: event_system_restart_copy ((CkLogSystemRestartEvent *) event, (CkLogSystemRestartEvent *) event_copy); break; case CK_LOG_EVENT_SYSTEM_START: event_system_start_copy ((CkLogSystemStartEvent *) event, (CkLogSystemStartEvent *) event_copy); break; case CK_LOG_EVENT_SYSTEM_SUSPEND: event_system_suspend_copy ((CkLogSystemSuspendEvent *) event, (CkLogSystemSuspendEvent *) event_copy); break; case CK_LOG_EVENT_SYSTEM_HIBERNATE: event_system_hibernate_copy ((CkLogSystemHibernateEvent *) event, (CkLogSystemHibernateEvent *) event_copy); break; case CK_LOG_EVENT_SEAT_SESSION_ADDED: event_seat_session_added_copy ((CkLogSeatSessionAddedEvent *) event, (CkLogSeatSessionAddedEvent *) event_copy); break; case CK_LOG_EVENT_SEAT_SESSION_REMOVED: event_seat_session_removed_copy ((CkLogSeatSessionRemovedEvent *) event, (CkLogSeatSessionRemovedEvent *) event_copy); break; case CK_LOG_EVENT_SEAT_DEVICE_ADDED: event_seat_device_added_copy ((CkLogSeatDeviceAddedEvent *) event, (CkLogSeatDeviceAddedEvent *) event_copy); break; case CK_LOG_EVENT_SEAT_DEVICE_REMOVED: event_seat_device_removed_copy ((CkLogSeatDeviceRemovedEvent *) event, (CkLogSeatDeviceRemovedEvent *) event_copy); break; case CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED: event_seat_active_session_changed_copy ((CkLogSeatActiveSessionChangedEvent *) event, (CkLogSeatActiveSessionChangedEvent *) event_copy); break; default: g_assert_not_reached (); break; } return event_copy; } void ck_log_event_free (CkLogEvent *event) { switch (event->type) { case CK_LOG_EVENT_SEAT_ADDED: event_seat_added_free ((CkLogSeatAddedEvent *) event); break; case CK_LOG_EVENT_SEAT_REMOVED: event_seat_removed_free ((CkLogSeatRemovedEvent *) event); break; case CK_LOG_EVENT_SYSTEM_STOP: event_system_stop_free ((CkLogSystemStopEvent *) event); break; case CK_LOG_EVENT_SYSTEM_RESTART: event_system_restart_free ((CkLogSystemRestartEvent *) event); break; case CK_LOG_EVENT_SYSTEM_START: event_system_start_free ((CkLogSystemStartEvent *) event); break; case CK_LOG_EVENT_SYSTEM_SUSPEND: event_system_suspend_free ((CkLogSystemSuspendEvent *) event); break; case CK_LOG_EVENT_SYSTEM_HIBERNATE: event_system_hibernate_free ((CkLogSystemHibernateEvent *) event); break; case CK_LOG_EVENT_SEAT_SESSION_ADDED: event_seat_session_added_free ((CkLogSeatSessionAddedEvent *) event); break; case CK_LOG_EVENT_SEAT_SESSION_REMOVED: event_seat_session_removed_free ((CkLogSeatSessionRemovedEvent *) event); break; case CK_LOG_EVENT_SEAT_DEVICE_ADDED: event_seat_device_added_free ((CkLogSeatDeviceAddedEvent *) event); break; case CK_LOG_EVENT_SEAT_DEVICE_REMOVED: event_seat_device_removed_free ((CkLogSeatDeviceRemovedEvent *) event); break; case CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED: event_seat_active_session_changed_free ((CkLogSeatActiveSessionChangedEvent *) event); break; default: g_assert_not_reached (); break; } g_free (event); } static void add_log_for_seat_added (GString *str, CkLogEvent *event) { CkLogSeatAddedEvent *e; e = (CkLogSeatAddedEvent *)event; g_string_append_printf (str, "seat-id='%s' seat-kind=%d", e->seat_id, e->seat_kind); } static void add_log_for_seat_removed (GString *str, CkLogEvent *event) { CkLogSeatRemovedEvent *e; e = (CkLogSeatRemovedEvent *)event; g_string_append_printf (str, "seat-id='%s' seat-kind=%d", e->seat_id, e->seat_kind); } static void add_log_for_seat_session_added (GString *str, CkLogEvent *event) { CkLogSeatSessionAddedEvent *e; e = (CkLogSeatSessionAddedEvent *)event; g_string_append_printf (str, "seat-id='%s' session-id='%s' session-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'", e->seat_id ? e->seat_id : "", e->session_id ? e->session_id : "", e->session_type ? e->session_type : "", e->session_x11_display ? e->session_x11_display : "", e->session_x11_display_device ? e->session_x11_display_device : "", e->session_display_device ? e->session_display_device : "", e->session_remote_host_name ? e->session_remote_host_name : "", e->session_is_local ? "TRUE" : "FALSE", e->session_unix_user, e->session_creation_time ? e->session_creation_time : ""); } static void add_log_for_seat_session_removed (GString *str, CkLogEvent *event) { CkLogSeatSessionRemovedEvent *e; e = (CkLogSeatSessionRemovedEvent *)event; g_string_append_printf (str, "seat-id='%s' session-id='%s' session-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'", e->seat_id ? e->seat_id : "", e->session_id ? e->session_id : "", e->session_type ? e->session_type : "", e->session_x11_display ? e->session_x11_display : "", e->session_x11_display_device ? e->session_x11_display_device : "", e->session_display_device ? e->session_display_device : "", e->session_remote_host_name ? e->session_remote_host_name : "", e->session_is_local ? "TRUE" : "FALSE", e->session_unix_user, e->session_creation_time ? e->session_creation_time : ""); } static void add_log_for_system_stop (GString *str, CkLogEvent *event) { /* TODO: Not implemented */ } static void add_log_for_system_restart (GString *str, CkLogEvent *event) { /* TODO: Not implemented */ } static void add_log_for_system_start (GString *str, CkLogEvent *event) { CkLogSystemStartEvent *e; e = (CkLogSystemStartEvent *)event; g_string_append_printf (str, "kernel-release='%s' boot-arguments='%s'", e->kernel_release ? e->kernel_release : "", e->boot_arguments ? e->boot_arguments : ""); } static void add_log_for_system_suspend (GString *str, CkLogEvent *event) { /* TODO: Not implemented */ } static void add_log_for_system_hibernate (GString *str, CkLogEvent *event) { /* TODO: Not implemented */ } static void add_log_for_seat_active_session_changed (GString *str, CkLogEvent *event) { CkLogSeatActiveSessionChangedEvent *e; e = (CkLogSeatActiveSessionChangedEvent *)event; g_string_append_printf (str, "seat-id='%s' session-id='%s'", e->seat_id ? e->seat_id : "", e->session_id ? e->session_id : ""); } static void add_log_for_seat_device_added (GString *str, CkLogEvent *event) { CkLogSeatDeviceAddedEvent *e; e = (CkLogSeatDeviceAddedEvent *)event; g_string_append_printf (str, "seat-id='%s' device-id='%s' device-type='%s'", e->seat_id ? e->seat_id : "", e->device_id ? e->device_id : "", e->device_type ? e->device_type : ""); } static void add_log_for_seat_device_removed (GString *str, CkLogEvent *event) { CkLogSeatDeviceRemovedEvent *e; e = (CkLogSeatDeviceRemovedEvent *)event; g_string_append_printf (str, "seat-id='%s' device-id='%s' device-type='%s'", e->seat_id ? e->seat_id : "", e->device_id ? e->device_id : "", e->device_type ? e->device_type : ""); } static const char * event_type_to_name (CkLogEventType event_type) { const char *str; switch (event_type) { case CK_LOG_EVENT_SEAT_ADDED: str = "SEAT_ADDED"; break; case CK_LOG_EVENT_SEAT_REMOVED: str = "SEAT_REMOVED"; break; case CK_LOG_EVENT_SYSTEM_STOP: str = "SYSTEM_STOP"; break; case CK_LOG_EVENT_SYSTEM_RESTART: str = "SYSTEM_RESTART"; break; case CK_LOG_EVENT_SYSTEM_START: str = "SYSTEM_START"; break; case CK_LOG_EVENT_SEAT_SESSION_ADDED: str = "SEAT_SESSION_ADDED"; break; case CK_LOG_EVENT_SEAT_SESSION_REMOVED: str = "SEAT_SESSION_REMOVED"; break; case CK_LOG_EVENT_SEAT_DEVICE_ADDED: str = "SEAT_DEVICE_ADDED"; break; case CK_LOG_EVENT_SEAT_DEVICE_REMOVED: str = "SEAT_DEVICE_REMOVED"; break; case CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED: str = "SEAT_ACTIVE_SESSION_CHANGED"; break; default: str = "UNKNOWN"; break; } return str; } static gboolean event_name_to_type (const char *event_name, CkLogEventType *event_type) { gboolean ret; ret = TRUE; if (strcmp (event_name, "SEAT_ADDED") == 0) { *event_type = CK_LOG_EVENT_SEAT_ADDED; } else if (strcmp (event_name, "SEAT_REMOVED") == 0) { *event_type = CK_LOG_EVENT_SEAT_REMOVED; } else if (strcmp (event_name, "SYSTEM_STOP") == 0) { *event_type = CK_LOG_EVENT_SYSTEM_STOP; } else if (strcmp (event_name, "SYSTEM_RESTART") == 0) { *event_type = CK_LOG_EVENT_SYSTEM_RESTART; } else if (strcmp (event_name, "SYSTEM_START") == 0) { *event_type = CK_LOG_EVENT_SYSTEM_START; } else if (strcmp (event_name, "SEAT_SESSION_ADDED") == 0) { *event_type = CK_LOG_EVENT_SEAT_SESSION_ADDED; } else if (strcmp (event_name, "SEAT_SESSION_REMOVED") == 0) { *event_type = CK_LOG_EVENT_SEAT_SESSION_REMOVED; } else if (strcmp (event_name, "SEAT_DEVICE_ADDED") == 0) { *event_type = CK_LOG_EVENT_SEAT_DEVICE_ADDED; } else if (strcmp (event_name, "SEAT_DEVICE_REMOVED") == 0) { *event_type = CK_LOG_EVENT_SEAT_DEVICE_REMOVED; } else if (strcmp (event_name, "SEAT_ACTIVE_SESSION_CHANGED") == 0) { *event_type = CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED; } else { ret = FALSE; } return ret; } static void add_log_for_any (GString *str, CkLogEvent *event) { g_string_append_printf (str, "%lu.%03u type=%s : ", (gulong)event->timestamp.tv_sec, (guint)(event->timestamp.tv_usec / 1000), event_type_to_name (event->type)); } void ck_log_event_to_string (CkLogEvent *event, GString *str) { add_log_for_any (str, event); switch (event->type) { case CK_LOG_EVENT_SEAT_ADDED: add_log_for_seat_added (str, event); break; case CK_LOG_EVENT_SEAT_REMOVED: add_log_for_seat_removed (str, event); break; case CK_LOG_EVENT_SYSTEM_STOP: add_log_for_system_stop (str, event); break; case CK_LOG_EVENT_SYSTEM_RESTART: add_log_for_system_restart (str, event); break; case CK_LOG_EVENT_SYSTEM_START: add_log_for_system_start (str, event); break; case CK_LOG_EVENT_SYSTEM_SUSPEND: add_log_for_system_suspend (str, event); break; case CK_LOG_EVENT_SYSTEM_HIBERNATE: add_log_for_system_hibernate (str, event); break; case CK_LOG_EVENT_SEAT_SESSION_ADDED: add_log_for_seat_session_added (str, event); break; case CK_LOG_EVENT_SEAT_SESSION_REMOVED: add_log_for_seat_session_removed (str, event); break; case CK_LOG_EVENT_SEAT_DEVICE_ADDED: add_log_for_seat_device_added (str, event); break; case CK_LOG_EVENT_SEAT_DEVICE_REMOVED: add_log_for_seat_device_removed (str, event); break; case CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED: add_log_for_seat_active_session_changed (str, event); break; default: g_assert_not_reached (); break; } } static const char * skip_header (const char *str, gssize len) { char *r; r = g_strstr_len (str, len, " : "); if (r != NULL) { r += 3; goto out; } r = g_strstr_len (str, len, " :"); if (r != NULL) { r += 2; } out: return r; } static gboolean parse_value_as_ulong (const char *value, gulong *intval) { char *end_of_valid_int; glong ulong_value; ulong_value = strtoul (value, &end_of_valid_int, 10); if (*value == '\0' || *end_of_valid_int != '\0') { return FALSE; } *intval = ulong_value; return TRUE; } static gboolean parse_log_for_seat_added (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; char *tmp; CkLogSeatAddedEvent *e; re = NULL; match_info = NULL; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } error = NULL; re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' seat-kind=(?P[0-9]*)", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse seat added event: %s", s); goto out; } e = (CkLogSeatAddedEvent *)event; e->seat_id = g_match_info_fetch_named (match_info, "seatid"); tmp = g_match_info_fetch_named (match_info, "seatkind"); if (tmp != NULL) { gulong l; if (parse_value_as_ulong (tmp, &l)) { e->seat_kind = l; } } ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_seat_removed (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; char *tmp; CkLogSeatRemovedEvent *e; re = NULL; match_info = NULL; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } error = NULL; re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' seat-kind=(?P[0-9]*)", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse seat removed event: %s", s); goto out; } e = (CkLogSeatRemovedEvent *)event; e->seat_id = g_match_info_fetch_named (match_info, "seatid"); tmp = g_match_info_fetch_named (match_info, "seatkind"); if (tmp != NULL) { gulong l; if (parse_value_as_ulong (tmp, &l)) { e->seat_kind = l; } } ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_system_stop (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } ret = TRUE; out: return ret; } static gboolean parse_log_for_system_restart (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } ret = TRUE; out: return ret; } static gboolean parse_log_for_system_start (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; CkLogSystemStartEvent *e; ret = FALSE; re = NULL; match_info = NULL; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } /* kernel-release and boot-arguments are attributes added in 0.4 */ error = NULL; re = g_regex_new ("(kernel-release='(?P[^']+)')?[ ]?(boot-arguments='(?P.*)')?", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse system start event: %s", s); goto out; } e = (CkLogSystemStartEvent *)event; e->kernel_release = g_match_info_fetch_named (match_info, "release"); e->boot_arguments = g_match_info_fetch_named (match_info, "arguments"); ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_seat_session_added (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; char *tmp; CkLogSeatSessionAddedEvent *e; re = NULL; match_info = NULL; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } error = NULL; re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' session-id='(?P[a-zA-Z0-9/]+)' session-type='(?P[a-zA-Z0-9 ]*)' session-x11-display='(?P[0-9a-zA-Z.:]*)' session-x11-display-device='(?P[^']*)' session-display-device='(?P[^']*)' session-remote-host-name='(?P[^']*)' session-is-local=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse session added event: %s", s); goto out; } e = (CkLogSeatSessionAddedEvent *)event; e->seat_id = g_match_info_fetch_named (match_info, "seatid"); e->session_id = g_match_info_fetch_named (match_info, "sessionid"); e->session_type = g_match_info_fetch_named (match_info, "sessiontype"); e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display"); e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice"); e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice"); e->session_remote_host_name = g_match_info_fetch_named (match_info, "sessionremotehostname"); e->session_creation_time = g_match_info_fetch_named (match_info, "sessioncreationtime"); tmp = g_match_info_fetch_named (match_info, "sessionislocal"); if (tmp != NULL && strcmp (tmp, "TRUE") == 0) { e->session_is_local = TRUE; } else { e->session_is_local = FALSE; } g_free (tmp); tmp = g_match_info_fetch_named (match_info, "sessionunixuser"); if (tmp != NULL) { gulong l; if (parse_value_as_ulong (tmp, &l)) { e->session_unix_user = l; } } ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_seat_session_removed (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; char *tmp; CkLogSeatSessionRemovedEvent *e; re = NULL; match_info = NULL; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } error = NULL; re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' session-id='(?P[a-zA-Z0-9/]+)' session-type='(?P[a-zA-Z0-9 ]*)' session-x11-display='(?P[0-9a-zA-Z.:]*)' session-x11-display-device='(?P[^']*)' session-display-device='(?P[^']*)' session-remote-host-name='(?P[^']*)' session-is-local=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse session removed event: %s", s); goto out; } e = (CkLogSeatSessionRemovedEvent *)event; e->seat_id = g_match_info_fetch_named (match_info, "seatid"); e->session_id = g_match_info_fetch_named (match_info, "sessionid"); e->session_type = g_match_info_fetch_named (match_info, "sessiontype"); e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display"); e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice"); e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice"); e->session_remote_host_name = g_match_info_fetch_named (match_info, "sessionremotehostname"); e->session_creation_time = g_match_info_fetch_named (match_info, "sessioncreationtime"); tmp = g_match_info_fetch_named (match_info, "sessionislocal"); if (tmp != NULL && strcmp (tmp, "TRUE") == 0) { e->session_is_local = TRUE; } else { e->session_is_local = FALSE; } g_free (tmp); tmp = g_match_info_fetch_named (match_info, "sessionunixuser"); if (tmp != NULL) { gulong l; if (parse_value_as_ulong (tmp, &l)) { e->session_unix_user = l; } } ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_seat_active_session_changed (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; CkLogSeatActiveSessionChangedEvent *e; re = NULL; match_info = NULL; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } error = NULL; re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' session-id='(?P[a-zA-Z0-9/]*)'", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse session changed event: %s", s); goto out; } e = (CkLogSeatActiveSessionChangedEvent *)event; e->seat_id = g_match_info_fetch_named (match_info, "seatid"); e->session_id = g_match_info_fetch_named (match_info, "sessionid"); ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_seat_device_added (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; CkLogSeatDeviceAddedEvent *e; re = NULL; match_info = NULL; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } error = NULL; re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' device-id='(?P[^']+)' device-type='(?P[^']+)'", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse device added event: %s", s); goto out; } e = (CkLogSeatDeviceAddedEvent *)event; e->seat_id = g_match_info_fetch_named (match_info, "seatid"); e->device_id = g_match_info_fetch_named (match_info, "deviceid"); e->device_type = g_match_info_fetch_named (match_info, "devicetype"); ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_seat_device_removed (const GString *str, CkLogEvent *event) { gboolean ret; const char *s; GRegex *re; GMatchInfo *match_info; gboolean res; GError *error; CkLogSeatDeviceRemovedEvent *e; re = NULL; match_info = NULL; ret = FALSE; s = skip_header (str->str, str->len); if (s == NULL) { goto out; } error = NULL; re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' device-id='(?P[^']+)' device-type='(?P[^']+)'", 0, 0, &error); if (re == NULL) { g_warning ("%s", error->message); goto out; } g_regex_match (re, s, 0, &match_info); res = g_match_info_matches (match_info); if (! res) { g_warning ("Unable to parse device removed event: %s", s); goto out; } e = (CkLogSeatDeviceRemovedEvent *)event; e->seat_id = g_match_info_fetch_named (match_info, "seatid"); e->device_id = g_match_info_fetch_named (match_info, "deviceid"); e->device_type = g_match_info_fetch_named (match_info, "devicetype"); ret = TRUE; out: if (match_info != NULL) { g_match_info_free (match_info); } if (re != NULL) { g_regex_unref (re); } return ret; } static gboolean parse_log_for_any (const GString *str, CkLogEvent *event) { gboolean ret; int res; gulong sec; guint frac; char buf[32]; ret = FALSE; res = sscanf (str->str, "%lu.%u type=%30s :", &sec, &frac, buf); if (res == 3) { res = event_name_to_type (buf, &event->type); if (! res) { goto out; } event->timestamp.tv_sec = sec; event->timestamp.tv_usec = 1000 * frac; ret = TRUE; } out: return ret; } gboolean ck_log_event_fill_from_string (CkLogEvent *event, const GString *str) { gboolean res; gboolean ret; g_return_val_if_fail (str != NULL, FALSE); ret = FALSE; res = parse_log_for_any (str, event); if (! res) { goto out; } switch (event->type) { case CK_LOG_EVENT_SEAT_ADDED: res = parse_log_for_seat_added (str, event); break; case CK_LOG_EVENT_SEAT_REMOVED: res = parse_log_for_seat_removed (str, event); break; case CK_LOG_EVENT_SYSTEM_STOP: res = parse_log_for_system_stop (str, event); break; case CK_LOG_EVENT_SYSTEM_RESTART: res = parse_log_for_system_restart (str, event); break; case CK_LOG_EVENT_SYSTEM_START: res = parse_log_for_system_start (str, event); break; case CK_LOG_EVENT_SEAT_SESSION_ADDED: res = parse_log_for_seat_session_added (str, event); break; case CK_LOG_EVENT_SEAT_SESSION_REMOVED: res = parse_log_for_seat_session_removed (str, event); break; case CK_LOG_EVENT_SEAT_DEVICE_ADDED: res = parse_log_for_seat_device_added (str, event); break; case CK_LOG_EVENT_SEAT_DEVICE_REMOVED: res = parse_log_for_seat_device_removed (str, event); break; case CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED: res = parse_log_for_seat_active_session_changed (str, event); break; default: g_assert_not_reached (); break; } if (! res) { goto out; } ret = TRUE; out: return ret; } CkLogEvent * ck_log_event_new_from_string (const GString *str) { CkLogEvent *event; gboolean res; g_return_val_if_fail (str != NULL, NULL); event = g_new0 (CkLogEvent, 1); res = ck_log_event_fill_from_string (event, str); if (! res) { g_free (event); event = NULL; } return event; } consolekit2-1.2.6/src/ck-log-event.h000066400000000000000000000111361446640754400172270ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_LOG_EVENT_H #define __CK_LOG_EVENT_H #include G_BEGIN_DECLS typedef enum { CK_LOG_EVENT_NONE = 0, CK_LOG_EVENT_START, CK_LOG_EVENT_STOP, CK_LOG_EVENT_SYSTEM_START, CK_LOG_EVENT_SYSTEM_STOP, CK_LOG_EVENT_SYSTEM_RESTART, CK_LOG_EVENT_SYSTEM_SUSPEND, CK_LOG_EVENT_SYSTEM_HIBERNATE, CK_LOG_EVENT_SYSTEM_RUNLEVEL_CHANGED, CK_LOG_EVENT_SEAT_ADDED, CK_LOG_EVENT_SEAT_REMOVED, CK_LOG_EVENT_SEAT_SESSION_ADDED, CK_LOG_EVENT_SEAT_SESSION_REMOVED, CK_LOG_EVENT_SEAT_DEVICE_ADDED, CK_LOG_EVENT_SEAT_DEVICE_REMOVED, CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED, } CkLogEventType; typedef struct { gpointer dummy; } CkLogNoneEvent; typedef struct { gpointer dummy; } CkLogSystemStopEvent; typedef struct { gpointer dummy; } CkLogSystemRestartEvent; typedef struct { char *kernel_release; char *boot_arguments; } CkLogSystemStartEvent; typedef struct { gpointer dummy; } CkLogSystemSuspendEvent; typedef struct { gpointer dummy; } CkLogSystemHibernateEvent; typedef struct { char *seat_id; int seat_kind; } CkLogSeatAddedEvent; typedef struct { char *seat_id; int seat_kind; } CkLogSeatRemovedEvent; typedef struct { char *seat_id; char *session_id; char *session_type; char *session_x11_display; char *session_x11_display_device; char *session_display_device; char *session_remote_host_name; gboolean session_is_local; guint session_unix_user; char *session_creation_time; } CkLogSeatSessionAddedEvent; typedef struct { char *seat_id; char *session_id; char *session_type; char *session_x11_display; char *session_x11_display_device; char *session_display_device; char *session_remote_host_name; gboolean session_is_local; guint session_unix_user; char *session_creation_time; } CkLogSeatSessionRemovedEvent; typedef struct { char *seat_id; char *session_id; } CkLogSeatActiveSessionChangedEvent; typedef struct { char *seat_id; char *device_type; char *device_id; } CkLogSeatDeviceAddedEvent; typedef struct { char *seat_id; char *device_type; char *device_id; } CkLogSeatDeviceRemovedEvent; typedef struct { union { CkLogNoneEvent none; CkLogSystemStartEvent system_start; CkLogSystemStopEvent system_stop; CkLogSystemRestartEvent system_restart; CkLogSeatAddedEvent seat_added; CkLogSeatRemovedEvent seat_removed; CkLogSeatSessionAddedEvent seat_session_added; CkLogSeatSessionRemovedEvent seat_session_removed; CkLogSeatActiveSessionChangedEvent seat_active_session_changed; CkLogSeatDeviceAddedEvent seat_device_added; CkLogSeatDeviceRemovedEvent seat_device_removed; } event; GTimeVal timestamp; CkLogEventType type; } CkLogEvent; CkLogEvent * ck_log_event_copy (CkLogEvent *event); void ck_log_event_free (CkLogEvent *event); CkLogEvent * ck_log_event_new_from_string (const GString *str); gboolean ck_log_event_fill_from_string (CkLogEvent *event, const GString *str); void ck_log_event_to_string (CkLogEvent *event, GString *str); G_END_DECLS #endif /* __CK_LOG_EVENT_H */ consolekit2-1.2.6/src/ck-log.c000066400000000000000000000127651446640754400161140ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Authors: William Jon McCann * */ #include "config.h" #include #include #include #include #include #include #include #include "ck-log.h" static gboolean initialized = FALSE; static int syslog_levels = (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); static void log_level_to_priority_and_prefix (GLogLevelFlags log_level, int *priorityp, const char **prefixp) { int priority; const char *prefix; /* Process the message prefix and priority */ switch (log_level & G_LOG_LEVEL_MASK) { case G_LOG_FLAG_FATAL: priority = LOG_EMERG; prefix = "FATAL"; break; case G_LOG_LEVEL_ERROR: priority = LOG_ERR; prefix = "ERROR"; break; case G_LOG_LEVEL_CRITICAL: priority = LOG_CRIT; prefix = "CRITICAL"; break; case G_LOG_LEVEL_WARNING: priority = LOG_WARNING; prefix = "WARNING"; break; case G_LOG_LEVEL_MESSAGE: priority = LOG_NOTICE; prefix = "MESSAGE"; break; case G_LOG_LEVEL_INFO: priority = LOG_INFO; prefix = "INFO"; break; case G_LOG_LEVEL_DEBUG: /* if debug was requested then bump this up to ERROR * to ensure it is seen in a log */ if (syslog_levels & G_LOG_LEVEL_DEBUG) { priority = LOG_WARNING; } else { priority = LOG_DEBUG; } prefix = "DEBUG"; break; default: priority = LOG_DEBUG; prefix = "UNKNOWN"; break; } if (priorityp != NULL) { *priorityp = priority; } if (prefixp != NULL) { *prefixp = prefix; } } void ck_log_default_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data) { GString *gstring; int priority; const char *level_prefix; char *string; gboolean do_log; gboolean is_fatal; is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0; do_log = (log_level & syslog_levels); if (! do_log) { return; } if (! initialized) { ck_log_init (); } log_level_to_priority_and_prefix (log_level, &priority, &level_prefix); gstring = g_string_new (NULL); if (log_domain != NULL) { g_string_append (gstring, log_domain); g_string_append_c (gstring, '-'); } g_string_append (gstring, level_prefix); g_string_append (gstring, ": "); if (message == NULL) { g_string_append (gstring, "(NULL) message"); } else { g_string_append (gstring, message); } if (is_fatal) { g_string_append (gstring, "\naborting...\n"); } else { g_string_append (gstring, "\n"); } string = g_string_free (gstring, FALSE); syslog (priority, "%s", string); g_free (string); } void ck_log_toggle_debug (void) { if (syslog_levels & G_LOG_LEVEL_DEBUG) { g_debug ("Debugging disabled"); syslog_levels &= ~G_LOG_LEVEL_DEBUG; } else { syslog_levels |= G_LOG_LEVEL_DEBUG; g_debug ("Debugging enabled"); } } void ck_log_set_debug (gboolean debug) { if (debug) { syslog_levels |= G_LOG_LEVEL_DEBUG; g_debug ("Debugging enabled"); } else { g_debug ("Debugging disabled"); syslog_levels &= ~G_LOG_LEVEL_DEBUG; } } void ck_log_init (void) { const char *prg_name; int options; g_log_set_default_handler (ck_log_default_handler, NULL); prg_name = g_get_prgname (); options = LOG_PID; #ifdef LOG_PERROR options |= LOG_PERROR; #endif openlog (prg_name, options, LOG_DAEMON); initialized = TRUE; } void ck_log_shutdown (void) { closelog (); initialized = FALSE; } consolekit2-1.2.6/src/ck-log.h000066400000000000000000000026451446640754400161150ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Authors: William Jon McCann * */ #ifndef __CK_LOG_H #define __CK_LOG_H #include G_BEGIN_DECLS void ck_log_default_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data); void ck_log_set_debug (gboolean debug); void ck_log_toggle_debug (void); void ck_log_init (void); void ck_log_shutdown (void); G_END_DECLS #endif /* __CK_LOG_H */ consolekit2-1.2.6/src/ck-manager.c000066400000000000000000004321011446640754400167330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006-2008 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined HAVE_POLKIT #include #elif defined ENABLE_RBAC_SHUTDOWN #include #include #endif #include "ck-manager.h" #include "ck-seat.h" #include "ck-session-leader.h" #include "ck-session.h" #include "ck-marshal.h" #include "ck-event-logger.h" #include "ck-inhibit-manager.h" #include "ck-inhibit.h" #include "ck-sysdeps.h" #include "ck-process-group.h" #define CK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_MANAGER, CkManagerPrivate)) #define CK_SEAT_DIR SYSCONFDIR "/ConsoleKit/seats.d" #define LOG_FILE LOCALSTATEDIR "/log/ConsoleKit/history" #define DBUS_NAME "org.freedesktop.ConsoleKit" #define CK_DBUS_PATH "/org/freedesktop/ConsoleKit" #define CK_MANAGER_DBUS_PATH CK_DBUS_PATH "/Manager" #define DBUS_SESSION_INTERFACE DBUS_NAME ".Session" #define DBUS_MANAGER_INTERFACE DBUS_NAME ".Manager" typedef enum { PREPARE_FOR_SHUTDOWN, PREPARE_FOR_SLEEP, LAST_SIGNAL } SIGNALS; typedef struct { CkManager *manager; GDBusMethodInvocation *context; const gchar *command; CkLogEventType event_type; const gchar *description; SIGNALS signal; } SystemActionData; struct CkManagerPrivate { #ifdef HAVE_POLKIT PolkitAuthority *pol_ctx; #endif GHashTable *seats; GHashTable *sessions; GHashTable *leaders; GDBusProxy *bus_proxy; GDBusConnection *connection; CkEventLogger *logger; guint name_owner_id; guint32 session_serial; guint32 seat_serial; gboolean system_idle_hint; GTimeVal system_idle_since_hint; /* How long to delay after emitting the PREPARE_FOR_SHUTDOWN or * PREPARE_FOR_SLEEP signal */ guint system_action_idle_delay; /* How long to delay after emitting the PREPARE_FOR_SHUTDOWN or * PREPARE_FOR_SLEEP signal with something holding the delay * inhibit */ guint system_action_idle_inhibited_delay; /* The idle callback id so we can detect multiple attempts to * perform a system action at the same time */ guint system_action_idle_id; /* Now that the action data can be delayed and that delay can * be lifted sooner than system_action_idle_inhibited_delay, * we need to keep a pointer to the system action data so we * can manually call system_action_idle_cb */ SystemActionData *system_action_data; CkInhibitManager *inhibit_manager; }; static void ck_manager_iface_init (ConsoleKitManagerIface *iface); static void ck_manager_finalize (GObject *object); static void remove_sessions_for_connection (CkManager *manager, const gchar *service_name); static void create_seats (CkManager *manager); static gboolean session_is_real_user (CkSession *session, char **userp); static gpointer manager_object = NULL; G_DEFINE_TYPE_WITH_CODE (CkManager, ck_manager, CONSOLE_KIT_TYPE_MANAGER_SKELETON, G_IMPLEMENT_INTERFACE (CONSOLE_KIT_TYPE_MANAGER, ck_manager_iface_init)); static void dump_manager_seat_iter (char *id, CkSeat *seat, GString *str) { char *seat_id; GError *error; error = NULL; if (! ck_seat_get_id (seat, &seat_id, &error)) { g_warning ("Cannot get seat id from manager: %s", error->message); g_error_free (error); } else { /* ; is the seperator between elements in the list. * per keyfile standards */ if (str->len > 0) { g_string_append_c (str, ';'); } g_string_append (str, seat_id); g_free (seat_id); } } static void dump_state_seat_iter (char *id, CkSeat *seat, GKeyFile *key_file) { ck_seat_dump (seat, key_file); } static void dump_state_session_iter (char *id, CkSession *session, GKeyFile *key_file) { ck_session_dump (session, key_file); } static void dump_state_leader_iter (char *id, CkSessionLeader *leader, GKeyFile *key_file) { ck_session_leader_dump (leader, key_file); } typedef struct { GString *sessions; gboolean is_local; } UserDataDump; static void dump_user_iter (guint *uid, UserDataDump *data, GKeyFile *key_file) { gchar *user_group = NULL; gchar *session_list = NULL; TRACE (); if (data == NULL) { g_critical ("ck-manager: dump_user_iter: data == NULL"); return; } if (uid == NULL) { g_critical ("ck-manager: dump_user_iter: uid == NULL"); return; } user_group = g_strdup_printf ("User %u", *uid); if (user_group == NULL) { g_critical ("ck-manager: dump_user_iter: user_group == NULL, OOM"); return; } session_list = g_string_free(data->sessions, FALSE); g_key_file_set_boolean (key_file, user_group, "is_local", data->is_local); g_key_file_set_string (key_file, user_group, "sessions", session_list); g_free (user_group); g_free (session_list); } static void collect_user_data_dump (const char *ssid, CkSession *session, GHashTable *hash) { char *username; guint uid; gboolean is_local; UserDataDump *data; TRACE (); g_debug ("ssid %s", ssid); /* ensure we filter out DMs and stuff */ if (session_is_real_user (session, &username)) { if (username != NULL) { uid = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION (session)); /* Try to get the existing data */ data = g_hash_table_lookup (hash, &uid); if (data == NULL) { data = g_new0 (UserDataDump, 1); if (data == NULL) { g_critical ("ck-manager: collect_user_data_dump: OOM"); return; } /* allocate space for our sessions string */ data->sessions = g_string_new(NULL); if (data->sessions == NULL) { g_critical ("ck-manager: collect_user_data_dump: OOM"); return; } /* place the data into the hash table */ g_hash_table_insert (hash, &uid, data); } if (data->sessions == NULL) { g_critical ("ck-manager: collect_user_data_dump: failed sanity check"); return; } /* ; is the seperator between elements in the list. * per keyfile standards */ if (data->sessions->len > 0) { g_string_append_c (data->sessions, ';'); } /* add the new ssid to the list */ g_string_append (data->sessions, ssid); /* update the is_local property, we set this to True * if one seat/session is local */ is_local = console_kit_session_get_is_local (CONSOLE_KIT_SESSION (session)); if (is_local) { data->is_local = is_local; } } } } static void dump_user_section (CkManager *manager, GKeyFile *key_file) { GHashTable *users_hash; TRACE (); /* using direct since there is no g_uint_hash or g_uint_equal */ users_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); /* populate the users_hash filling in the user details */ g_hash_table_foreach (manager->priv->sessions, (GHFunc)collect_user_data_dump, users_hash); /* now print out each entry in a user section */ g_hash_table_foreach (users_hash, (GHFunc)dump_user_iter, key_file); g_hash_table_destroy (users_hash); } static gboolean do_dump (CkManager *manager, int fd) { char *str; char *s; gsize str_len; GString *seats_string; GKeyFile *key_file; GError *error; gboolean ret; str = NULL; error = NULL; ret = FALSE; key_file = g_key_file_new (); /* Create the [seats] section listing all the seats */ seats_string = g_string_new (NULL); g_hash_table_foreach (manager->priv->seats, (GHFunc) dump_manager_seat_iter, seats_string); s = g_string_free (seats_string, FALSE); g_key_file_set_string (key_file, "Seats", "seats", s); g_free (s); g_hash_table_foreach (manager->priv->seats, (GHFunc) dump_state_seat_iter, key_file); g_hash_table_foreach (manager->priv->sessions, (GHFunc) dump_state_session_iter, key_file); g_hash_table_foreach (manager->priv->leaders, (GHFunc) dump_state_leader_iter, key_file); dump_user_section (manager, key_file); str = g_key_file_to_data (key_file, &str_len, &error); g_key_file_free (key_file); if (str != NULL) { ssize_t written; written = 0; while ((size_t)written < str_len) { ssize_t num_written; num_written = write (fd, str + written, str_len - written); if (num_written < 0) { if (errno == EAGAIN || errno == EINTR) { continue; } else { g_warning ("Error writing state file: %s", strerror (errno)); goto out; } } written += num_written; } } else { g_warning ("Couldn't construct state file: %s", error->message); g_error_free (error); } ret = TRUE; out: g_free (str); return ret; } static void ck_manager_dump (CkManager *manager) { int fd; int res; const char *filename = RUNDIR "/ConsoleKit/database"; const char *filename_tmp = RUNDIR "/ConsoleKit/database~"; if (manager == NULL) { g_warning ("ck_manager_dump: manager == NULL"); return; } /* always make sure we have a directory */ errno = 0; res = g_mkdir_with_parents (RUNDIR "/ConsoleKit", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (res < 0) { g_warning ("Unable to create directory %s (%s)", RUNDIR "/ConsoleKit", g_strerror (errno)); return; } g_debug ("ck_manager_dump: %s/ConsoleKit folder created", RUNDIR); fd = g_open (filename_tmp, O_CREAT | O_WRONLY, 0644); if (fd == -1) { g_warning ("Cannot create file %s: %s", filename_tmp, g_strerror (errno)); goto error; } g_debug ("ck_manager_dump: %s created", filename_tmp); if (! do_dump (manager, fd)) { g_warning ("Cannot write to file %s", filename_tmp); close (fd); goto error; } g_debug ("ck_manager_dump: wrote database to %s", filename_tmp); again: if (close (fd) != 0) { if (errno == EINTR) goto again; else { g_warning ("Cannot close fd for %s: %s", filename_tmp, g_strerror (errno)); goto error; } } if (g_rename (filename_tmp, filename) != 0) { g_warning ("Cannot rename %s to %s: %s", filename_tmp, filename, g_strerror (errno)); goto error; } g_debug ("ck_manager_dump: renamed %s to %s, operation successful", filename_tmp, filename); return; error: /* For security reasons; unlink the existing file since it contains outdated information */ if (g_unlink (filename) != 0) { g_warning ("Cannot unlink %s: %s", filename, g_strerror (errno)); } } static const GDBusErrorEntry ck_manager_error_entries[] = { { CK_MANAGER_ERROR_FAILED, DBUS_MANAGER_INTERFACE ".Error.Failed" }, { CK_MANAGER_ERROR_GENERAL, DBUS_MANAGER_INTERFACE ".Error.General" }, { CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, DBUS_MANAGER_INTERFACE ".Error.InsufficientPermission" }, { CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, DBUS_MANAGER_INTERFACE ".Error.AuthorizationRequired" }, { CK_MANAGER_ERROR_BUSY, DBUS_MANAGER_INTERFACE ".Error.Busy" }, { CK_MANAGER_ERROR_NOT_SUPPORTED, DBUS_MANAGER_INTERFACE ".Error.NotSupported" }, { CK_MANAGER_ERROR_INHIBITED, DBUS_MANAGER_INTERFACE ".Error.Inhibited" }, { CK_MANAGER_ERROR_INVALID_INPUT, DBUS_MANAGER_INTERFACE ".Error.InvalidInput" }, { CK_MANAGER_ERROR_OOM, DBUS_MANAGER_INTERFACE ".Error.OutOfMemory" }, { CK_MANAGER_ERROR_NO_SEATS, DBUS_MANAGER_INTERFACE ".Error.NoSeats" }, { CK_MANAGER_ERROR_NO_SESSIONS, DBUS_MANAGER_INTERFACE ".Error.NoSessions" }, { CK_MANAGER_ERROR_NOTHING_INHIBITED, DBUS_MANAGER_INTERFACE ".Error.NothingInhibited" }, }; GQuark ck_manager_error_quark (void) { static volatile gsize quark_volatile = 0; g_dbus_error_register_error_domain ("ck_manager_error", &quark_volatile, ck_manager_error_entries, G_N_ELEMENTS (ck_manager_error_entries)); return (GQuark) quark_volatile; } #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } GType ck_manager_error_get_type (void) { static GType etype = 0; if (etype == 0) { static const GEnumValue values[] = { ENUM_ENTRY (CK_MANAGER_ERROR_FAILED, "Failed"), ENUM_ENTRY (CK_MANAGER_ERROR_GENERAL, "General"), ENUM_ENTRY (CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, "InsufficientPermission"), ENUM_ENTRY (CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, "AuthorizationRequired" ), ENUM_ENTRY (CK_MANAGER_ERROR_BUSY, "Busy" ), ENUM_ENTRY (CK_MANAGER_ERROR_NOT_SUPPORTED, "NotSupported"), ENUM_ENTRY (CK_MANAGER_ERROR_INHIBITED, "Inhibited"), ENUM_ENTRY (CK_MANAGER_ERROR_INVALID_INPUT, "InvalidInput"), ENUM_ENTRY (CK_MANAGER_ERROR_OOM, "OutOfMemory"), ENUM_ENTRY (CK_MANAGER_ERROR_NO_SEATS, "NoSeats"), ENUM_ENTRY (CK_MANAGER_ERROR_NO_SESSIONS, "NoSessions"), ENUM_ENTRY (CK_MANAGER_ERROR_NOTHING_INHIBITED, "NothingInhibited"), { 0, 0, 0 } }; g_assert (CK_MANAGER_NUM_ERRORS == G_N_ELEMENTS (values) - 1); etype = g_enum_register_static ("Error", values); } return etype; } static void throw_error (GDBusMethodInvocation *context, gint error_code, const gchar *format, ...) { va_list args; gchar *message; va_start (args, format); message = g_strdup_vprintf (format, args); va_end (args); g_debug ("manager: throwing error: %s", message); g_dbus_method_invocation_return_error (context, CK_MANAGER_ERROR, error_code, "%s", message); g_free (message); } static guint32 get_next_session_serial (CkManager *manager) { guint32 serial; serial = manager->priv->session_serial++; if ((gint32)manager->priv->session_serial < 0) { manager->priv->session_serial = 1; } return serial; } static guint32 get_next_seat_serial (CkManager *manager) { guint32 serial; serial = manager->priv->seat_serial++; if ((gint32)manager->priv->seat_serial < 0) { manager->priv->seat_serial = 0; } return serial; } static char * generate_session_cookie (CkManager *manager) { guint32 num; char *cookie; GTimeVal tv; char *uuid; uuid = g_strdup (g_get_host_name ()); /* We want this to be globally unique or at least such that it won't cycle when there may be orphan processes in a dead session. */ cookie = NULL; again: num = (guint32)g_random_int_range (1, G_MAXINT32); g_get_current_time (&tv); g_free (cookie); cookie = g_strdup_printf ("%s-%ld.%ld-%u", uuid, tv.tv_sec, tv.tv_usec, num); if (g_hash_table_lookup (manager->priv->leaders, cookie)) { goto again; } g_free (uuid); return cookie; } static char * generate_session_id (CkManager *manager) { guint32 serial; char *id; id = NULL; again: serial = get_next_session_serial (manager); g_free (id); id = g_strdup_printf ("%s/Session%u", CK_DBUS_PATH, serial); if (g_hash_table_lookup (manager->priv->sessions, id)) { goto again; } return id; } static char * generate_seat_id (CkManager *manager) { guint32 serial; char *id; id = NULL; again: serial = get_next_seat_serial (manager); g_free (id); id = g_strdup_printf ("%s/seat%u", CK_DBUS_PATH, serial); if (g_hash_table_lookup (manager->priv->seats, id)) { goto again; } return id; } static const char * get_object_id_basename (const char *id) { const char *base; if (id != NULL && g_str_has_prefix (id, CK_DBUS_PATH "/")) { base = id + strlen (CK_DBUS_PATH "/"); } else { base = id; } return base; } static void log_seat_added_event (CkManager *manager, CkSeat *seat) { CkLogEvent event; gboolean res; GError *error; char *sid; CkSeatKind seat_kind; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_ADDED; g_get_current_time (&event.timestamp); sid = NULL; ck_seat_get_id (seat, &sid, NULL); ck_seat_get_kind (seat, &seat_kind, NULL); event.event.seat_added.seat_id = (char *)get_object_id_basename (sid); event.event.seat_added.seat_kind = (int)seat_kind; error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } g_free (sid); } static void log_seat_removed_event (CkManager *manager, CkSeat *seat) { CkLogEvent event; gboolean res; GError *error; char *sid; CkSeatKind seat_kind; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_REMOVED; g_get_current_time (&event.timestamp); sid = NULL; ck_seat_get_id (seat, &sid, NULL); ck_seat_get_kind (seat, &seat_kind, NULL); event.event.seat_removed.seat_id = (char *)get_object_id_basename (sid); event.event.seat_removed.seat_kind = (int)seat_kind; error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } g_free (sid); } /* Generic logger for system actions such as CK_LOG_EVENT_SYSTEM_STOP, * restart, hibernate, and suspend */ static void log_system_action_event (CkManager *manager, CkLogEventType type) { CkLogEvent event; gboolean res; GError *error; memset (&event, 0, sizeof (CkLogEvent)); event.type = type; g_get_current_time (&event.timestamp); error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } /* FIXME: in this case we should block and wait for log to flush */ } static void log_seat_session_added_event (CkManager *manager, CkSeat *seat, const char *ssid) { CkLogEvent event; gboolean res; GError *error; char *sid; CkSession *session; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_SESSION_ADDED; g_get_current_time (&event.timestamp); sid = NULL; ck_seat_get_id (seat, &sid, NULL); event.event.seat_session_added.seat_id = (char *)get_object_id_basename (sid); event.event.seat_session_added.session_id = (char *)get_object_id_basename (ssid); session = g_hash_table_lookup (manager->priv->sessions, ssid); if (session != NULL) { g_object_get (session, "session-type", &event.event.seat_session_added.session_type, "x11-display", &event.event.seat_session_added.session_x11_display, "x11-display-device", &event.event.seat_session_added.session_x11_display_device, "display-device", &event.event.seat_session_added.session_display_device, "remote-host-name", &event.event.seat_session_added.session_remote_host_name, "is-local", &event.event.seat_session_added.session_is_local, "unix-user", &event.event.seat_session_added.session_unix_user, NULL); ck_session_get_creation_time (session, &event.event.seat_session_added.session_creation_time, NULL); g_debug ("Got uid: %u", event.event.seat_session_added.session_unix_user); } else { } error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } g_free (sid); g_free (event.event.seat_session_added.session_type); g_free (event.event.seat_session_added.session_x11_display); g_free (event.event.seat_session_added.session_x11_display_device); g_free (event.event.seat_session_added.session_display_device); g_free (event.event.seat_session_added.session_remote_host_name); g_free (event.event.seat_session_added.session_creation_time); } static void log_seat_session_removed_event (CkManager *manager, CkSeat *seat, const char *ssid) { CkLogEvent event; gboolean res; GError *error; char *sid; CkSession *session; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_SESSION_REMOVED; g_get_current_time (&event.timestamp); sid = NULL; ck_seat_get_id (seat, &sid, NULL); event.event.seat_session_removed.seat_id = (char *)get_object_id_basename (sid); event.event.seat_session_removed.session_id = (char *)get_object_id_basename (ssid); session = g_hash_table_lookup (manager->priv->sessions, ssid); if (session != NULL) { g_object_get (session, "session-type", &event.event.seat_session_removed.session_type, "x11-display", &event.event.seat_session_removed.session_x11_display, "x11-display-device", &event.event.seat_session_removed.session_x11_display_device, "display-device", &event.event.seat_session_removed.session_display_device, "remote-host-name", &event.event.seat_session_removed.session_remote_host_name, "is-local", &event.event.seat_session_removed.session_is_local, "unix-user", &event.event.seat_session_removed.session_unix_user, NULL); ck_session_get_creation_time (session, &event.event.seat_session_removed.session_creation_time, NULL); g_debug ("Got uid: %u", event.event.seat_session_removed.session_unix_user); } error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } g_free (sid); g_free (event.event.seat_session_removed.session_type); g_free (event.event.seat_session_removed.session_x11_display); g_free (event.event.seat_session_removed.session_x11_display_device); g_free (event.event.seat_session_removed.session_display_device); g_free (event.event.seat_session_removed.session_remote_host_name); g_free (event.event.seat_session_removed.session_creation_time); } static void log_seat_active_session_changed_event (CkManager *manager, CkSeat *seat, const char *ssid) { CkLogEvent event; gboolean res; GError *error; char *sid; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_ACTIVE_SESSION_CHANGED; g_get_current_time (&event.timestamp); sid = NULL; ck_seat_get_id (seat, &sid, NULL); event.event.seat_active_session_changed.seat_id = (char *)get_object_id_basename (sid); event.event.seat_active_session_changed.session_id = (char *)get_object_id_basename (ssid); error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } g_free (sid); } static void log_seat_device_added_event (CkManager *manager, CkSeat *seat, GVariant *device) { CkLogEvent event; gboolean res; GError *error; char *sid; char *device_id; char *device_type; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_DEVICE_ADDED; g_get_current_time (&event.timestamp); sid = NULL; device_type = NULL; device_id = NULL; ck_seat_get_id (seat, &sid, NULL); g_variant_get (device, "(ss)", &device_type, &device_id); event.event.seat_device_added.seat_id = (char *)get_object_id_basename (sid); event.event.seat_device_added.device_id = device_id; event.event.seat_device_added.device_type = device_type; error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } g_free (sid); g_free (device_type); g_free (device_id); } static void log_seat_device_removed_event (CkManager *manager, CkSeat *seat, GVariant *device) { CkLogEvent event; gboolean res; GError *error; char *sid; char *device_id; char *device_type; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_DEVICE_REMOVED; g_get_current_time (&event.timestamp); sid = NULL; device_type = NULL; device_id = NULL; ck_seat_get_id (seat, &sid, NULL); g_variant_get (device, "(ss)", &device_type, &device_id); event.event.seat_device_removed.seat_id = (char *)get_object_id_basename (sid); event.event.seat_device_removed.device_id = device_id; event.event.seat_device_removed.device_type = device_type; error = NULL; res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); if (! res) { g_debug ("Unable to log event: %s", error->message); g_error_free (error); } g_free (sid); g_free (device_type); g_free (device_id); } static char * get_cookie_for_pid (CkManager *manager, guint pid) { char *cookie = NULL; gchar *ssid = NULL; CkProcessGroup *pgroup; CkSession *session; pgroup = ck_process_group_get (); ssid = ck_process_group_get_ssid (pgroup, pid); if (ssid != NULL) { g_debug ("looking for session for ssid %s", ssid); session = g_hash_table_lookup (manager->priv->sessions, ssid); if (session != NULL) { g_object_get (session, "cookie", &cookie, NULL); } g_free (ssid); } if (cookie == NULL) { cookie = ck_unix_pid_get_env (pid, "XDG_SESSION_COOKIE"); } return cookie; } typedef void (*AuthorizedCallback) (CkManager *manager, GDBusMethodInvocation *context); typedef struct { CkManager *manager; GDBusMethodInvocation *context; AuthorizedCallback callback; } AuthorizedCallbackData; #ifdef HAVE_POLKIT static void data_free (AuthorizedCallbackData *data) { g_object_unref (data->manager); g_free (data); } static void auth_ready_callback (PolkitAuthority *authority, GAsyncResult *res, AuthorizedCallbackData *data) { GError *error; PolkitAuthorizationResult *result; error = NULL; result = polkit_authority_check_authorization_finish (authority, res, &error); if (error != NULL) { throw_error (data->context, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, _("Not Authorized: %s"), error->message); g_clear_error (&error); } else if (polkit_authorization_result_get_is_authorized (result)) { data->callback (data->manager, data->context); } else if (polkit_authorization_result_get_is_challenge (result)) { throw_error (data->context, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, _("Authorization is required")); } else { throw_error (data->context, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, _("Not Authorized")); } g_object_unref (result); data_free (data); } static void check_polkit_permissions (CkManager *manager, GDBusMethodInvocation *context, const char *action, gboolean policykit_interactivity, AuthorizedCallback callback) { const char *sender; PolkitSubject *subject; AuthorizedCallbackData *data; PolkitCheckAuthorizationFlags auth_flag; g_debug ("constructing polkit data"); /* Check that caller is privileged */ sender = g_dbus_method_invocation_get_sender (context); subject = polkit_system_bus_name_new (sender); auth_flag = policykit_interactivity ? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION : POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE; g_debug ("checking if caller %s is authorized", sender); data = g_new0 (AuthorizedCallbackData, 1); data->manager = g_object_ref (manager); data->context = context; data->callback = callback; polkit_authority_check_authorization (manager->priv->pol_ctx, subject, action, NULL, auth_flag, NULL, (GAsyncReadyCallback)auth_ready_callback, data); g_object_unref (subject); } static void ready_cb (PolkitAuthority *authority, GAsyncResult *res, GDBusMethodInvocation *context) { PolkitAuthorizationResult *ret; GError *error; error = NULL; ret = polkit_authority_check_authorization_finish (authority, res, &error); if (error != NULL) { throw_error (context, CK_MANAGER_ERROR_FAILED, error->message); g_clear_error (&error); } else if (polkit_authorization_result_get_is_authorized (ret)) { g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", TRUE)); } else if (polkit_authorization_result_get_is_challenge (ret)) { g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", TRUE)); } else { g_dbus_method_invocation_return_value (context, g_variant_new ("(b)", FALSE)); } g_object_unref (ret); } /* We use this to avoid breaking API compability with ConsoleKit1 for * CanStop and CanRestart, but this method emulates how logind * presents it's API */ static void logind_ready_cb (PolkitAuthority *authority, GAsyncResult *res, GDBusMethodInvocation *context) { PolkitAuthorizationResult *ret; GError *error; error = NULL; ret = polkit_authority_check_authorization_finish (authority, res, &error); if (error != NULL) { throw_error (context, CK_MANAGER_ERROR_FAILED, error->message); g_clear_error (&error); } else if (polkit_authorization_result_get_is_authorized (ret)) { g_dbus_method_invocation_return_value (context, g_variant_new ("(s)", "yes")); } else if (polkit_authorization_result_get_is_challenge (ret)) { g_dbus_method_invocation_return_value (context, g_variant_new ("(s)", "challenge")); } else { g_dbus_method_invocation_return_value (context, g_variant_new ("(s)", "no")); } g_object_unref (ret); } /* We use this to avoid breaking API compability with ConsoleKit1 for * CanStop and CanRestart, but this method emulates how logind * presents it's API */ static void get_polkit_logind_permissions (CkManager *manager, const char *action, GDBusMethodInvocation *context) { const char *sender; PolkitSubject *subject; g_debug ("get permissions for action %s", action); sender = g_dbus_method_invocation_get_sender (context); subject = polkit_system_bus_name_new (sender); polkit_authority_check_authorization (manager->priv->pol_ctx, subject, action, NULL, 0, NULL, (GAsyncReadyCallback) logind_ready_cb, context); g_object_unref (subject); } static void get_polkit_permissions (CkManager *manager, const char *action, GDBusMethodInvocation *context) { const char *sender; PolkitSubject *subject; g_debug ("get permissions for action %s", action); sender = g_dbus_method_invocation_get_sender (context); subject = polkit_system_bus_name_new (sender); polkit_authority_check_authorization (manager->priv->pol_ctx, subject, action, NULL, 0, NULL, (GAsyncReadyCallback) ready_cb, context); g_object_unref (subject); } #endif /* adapted from PolicyKit */ static gboolean get_caller_info (CkManager *manager, const char *sender, uid_t *calling_uid, pid_t *calling_pid) { gboolean res = FALSE; GVariant *value = NULL; GError *error = NULL; if (sender == NULL) { g_debug ("sender == NULL"); goto out; } if (manager->priv->bus_proxy == NULL) { g_debug ("manager->priv->bus_proxy == NULL"); goto out; } value = g_dbus_proxy_call_sync (manager->priv->bus_proxy, "GetConnectionUnixUser", g_variant_new ("(s)", sender), G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &error); if (value == NULL) { g_warning ("GetConnectionUnixUser() failed: %s", error->message); g_error_free (error); goto out; } g_variant_get (value, "(u)", calling_uid); g_variant_unref (value); value = g_dbus_proxy_call_sync (manager->priv->bus_proxy, "GetConnectionUnixProcessID", g_variant_new ("(s)", sender), G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &error); if (value == NULL) { g_warning ("GetConnectionUnixProcessID() failed: %s", error->message); g_error_free (error); goto out; } g_variant_get (value, "(u)", calling_pid); g_variant_unref (value); res = TRUE; g_debug ("uid = %d", *calling_uid); g_debug ("pid = %d", *calling_pid); out: return res; } static char * get_user_name (uid_t uid) { struct passwd *pwent; char *name; name = NULL; pwent = getpwuid (uid); if (pwent != NULL) { name = g_strdup (pwent->pw_name); } return name; } static gboolean session_is_real_user (CkSession *session, char **userp) { int uid; char *username; char *session_type; gboolean ret; ret = FALSE; session_type = NULL; username = NULL; session_type = NULL; g_object_get (session, "unix-user", &uid, "session-type", &session_type, NULL); username = get_user_name (uid); /* filter out GDM/SDDM/KDM user */ if (g_strcmp0 (username, "gdm") == 0 || g_strcmp0 (username, "_gdm") == 0 || g_strcmp0 (username, "sddm") == 0 || g_strcmp0 (username, "_sddm") == 0 || g_strcmp0 (username, "kdm") == 0 || g_strcmp0 (username, "_kdm") == 0) { ret = FALSE; goto out; } if (userp != NULL) { *userp = g_strdup (username); } ret = TRUE; out: g_free (username); g_free (session_type); return ret; } static void collect_users (const char *ssid, CkSession *session, GHashTable *hash) { char *username; if (session_is_real_user (session, &username)) { if (username != NULL) { g_hash_table_insert (hash, username, NULL); } } } static guint get_system_num_users (CkManager *manager) { guint num_users; GHashTable *hash; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_hash_table_foreach (manager->priv->sessions, (GHFunc)collect_users, hash); num_users = g_hash_table_size (hash); g_hash_table_destroy (hash); g_debug ("found %u unique users", num_users); return num_users; } static gboolean session_has_user (const char *ssid, CkSession *session, guint *unix_user) { guint session_user; session_user = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION (session)); if (session_user == *unix_user) { g_debug ("Found session for user %d", *unix_user); return TRUE; } return FALSE; } static const gchar * get_runtime_dir_for_user (CkManager *manager, guint unix_user) { gpointer session; TRACE (); session = g_hash_table_find (manager->priv->sessions, (GHRFunc)session_has_user, &unix_user); if (session != NULL) { return ck_session_get_runtime_dir (CK_SESSION (session)); } return NULL; } #ifdef ENABLE_RBAC_SHUTDOWN static gboolean check_rbac_permissions (CkManager *manager, GDBusMethodInvocation *context, const char *action, AuthorizedCallback callback) { const char *sender; char *username; gboolean res; uid_t uid = 0; pid_t pid = 0; username = NULL; sender = g_dbus_method_invocation_get_sender (context); res = get_caller_info (manager, sender, &uid, &pid); if (!res) { goto out; } username = get_user_name (uid); if (username == NULL || !chkauthattr (action, username)) { res = FALSE; goto out; } out: if (res == TRUE) { g_debug ("User %s has RBAC permission to stop/restart", username); } else { g_debug ("User %s does not have RBAC permission to %s", username, action); } g_free (username); if (res && callback) { callback (manager, context); } return res; } #endif /* Performs the callback if the user has permissions authorizing them either * via the RBAC_SHUTDOWN_KEY or PolicyKit action. The policykit_interactivity * flag is used only by PolicyKit to determine if the user should be prompted * for their password if can returns a "challenge" response. */ static void check_system_action (CkManager *manager, gboolean policykit_interactivity, GDBusMethodInvocation *context, const char *action, AuthorizedCallback callback) { g_return_if_fail (callback != NULL); g_return_if_fail (action != NULL); #if defined HAVE_POLKIT check_polkit_permissions (manager, context, action, policykit_interactivity, callback); #elif defined ENABLE_RBAC_SHUTDOWN check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, callback); #else g_warning ("Compiled without PolicyKit or RBAC support!"); callback(manager, context); #endif } /* Determines if the user can perform the action via PolicyKit, rbac, or * otherwise. * Only used for the 0.9.0+ calls, not CanStop or CanRestart as they * return a boolean. */ static void check_can_action (CkManager *manager, GDBusMethodInvocation *context, const char *action) { #if defined HAVE_POLKIT /* This will return the yes, no, and challenge */ get_polkit_logind_permissions (manager, action, context); #elif defined ENABLE_RBAC_SHUTDOWN /* rbac determines either yes or no. There is no challenge with rbac */ if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, NULL)) { g_dbus_method_invocation_return_value (context, g_variant_new ("(s)", "yes")); } else { g_dbus_method_invocation_return_value (context, g_variant_new ("(s)","no")); } #else /* neither polkit or rbac. assumed single user system */ g_dbus_method_invocation_return_value (context, g_variant_new ("(s)", "yes")); #endif } /* Logs the event and performs the system call such as ck-system-restart. * returns an error message over dbus to the user if needed, otherwise returns * success (also over dbus). */ static void do_system_action (CkManager *manager, GDBusMethodInvocation *context, const gchar *command, CkLogEventType event_type, const gchar *description) { GError *error; gboolean res; g_debug ("ConsoleKit preforming %s", description); log_system_action_event (manager, event_type); g_debug ("command is %s", command); error = NULL; res = g_spawn_command_line_sync (command, NULL, NULL, NULL, &error); if (! res) { g_warning ("Unable to %s system: %s", description, error->message); throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to %s system: %s"), description, error->message); g_clear_error (&error); } else { g_dbus_method_invocation_return_value (context, NULL); } } static gboolean system_action_idle_cb(SystemActionData *data) { g_return_val_if_fail (data != NULL, FALSE); /* Perform the action, it will handle the g_dbus_method_return */ do_system_action (data->manager, data->context, data->command, data->event_type, data->description); /* If we got here the sleep/shutdown action is done and we're awake again * or the operation failed. Either way we can signal to the apps */ switch (data->signal) { case PREPARE_FOR_SHUTDOWN: console_kit_manager_emit_prepare_for_shutdown (CONSOLE_KIT_MANAGER (data->manager), FALSE); break; case PREPARE_FOR_SLEEP: console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (data->manager), FALSE); break; default: g_error ("system_action_idle_cb, unknown signal for command %s", data->command); } /* reset this since we'll return FALSE here and kill the cb */ data->manager->priv->system_action_idle_id = 0; /* set this to NULL as we've processed this event and are about * to free the data */ data->manager->priv->system_action_data = NULL; g_free (data); return FALSE; } static void do_restart (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); return; } /* Emit the signal */ console_kit_manager_emit_prepare_for_shutdown (CONSOLE_KIT_MANAGER (manager), TRUE); /* Allocate and fill the data struct to pass to the idle cb */ data = g_new0 (SystemActionData, 1); if (data == NULL) { g_critical ("failed to allocate memory to perform shutdown\n"); console_kit_manager_emit_prepare_for_shutdown (CONSOLE_KIT_MANAGER (manager), FALSE); throw_error (context, CK_MANAGER_ERROR_FAILED, _("failed to allocate memory to perform restart")); return; } data->manager = manager; data->context = context; data->command = LIBDIR "/ConsoleKit/scripts/ck-system-restart"; data->event_type = CK_LOG_EVENT_SYSTEM_RESTART; data->description = "Restart"; data->signal = PREPARE_FOR_SHUTDOWN; if (ck_inhibit_manager_is_shutdown_delayed (manager->priv->inhibit_manager)) { delay_time = manager->priv->system_action_idle_inhibited_delay; /* We need to keep a pointer to the system action data because * the inhibit lock can be lifted before the timeout */ manager->priv->system_action_data = data; } else { delay_time = manager->priv->system_action_idle_delay; } /* Sleep so user applications have time to respond */ manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.Restart */ static gboolean dbus_restart (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); /* Check if something is blocking that action */ if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.restart-multiple-users"; } else { action = "org.freedesktop.consolekit.system.restart"; } g_debug ("ConsoleKit Restart: %s", action); check_system_action (manager, TRUE, context, action, do_restart); return TRUE; } static gboolean dbus_can_restart (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { #if defined HAVE_POLKIT const char *action = "org.freedesktop.consolekit.system.restart"; get_polkit_permissions (CK_MANAGER (ckmanager), action, context); #elif defined ENABLE_RBAC_SHUTDOWN if (check_rbac_permissions (CK_MANAGER (ckmanager), context, RBAC_SHUTDOWN_KEY, NULL)) { console_kit_manager_complete_can_restart (ckmanager, context , TRUE); } else { console_kit_manager_complete_can_restart (ckmanager, context , FALSE); } #else console_kit_manager_complete_can_restart (ckmanager, context , TRUE); #endif return TRUE; } static void do_stop (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); return; } /* Emit the signal */ console_kit_manager_emit_prepare_for_shutdown (CONSOLE_KIT_MANAGER (manager), TRUE); /* Allocate and fill the data struct to pass to the idle cb */ data = g_new0 (SystemActionData, 1); if (data == NULL) { g_critical ("failed to allocate memory to perform shutdown\n"); console_kit_manager_emit_prepare_for_shutdown (CONSOLE_KIT_MANAGER (manager), FALSE); throw_error (context, CK_MANAGER_ERROR_FAILED, _("failed to allocate memory to perform shutdown")); return; } data->manager = manager; data->context = context; data->command = LIBDIR "/ConsoleKit/scripts/ck-system-stop"; data->event_type = CK_LOG_EVENT_SYSTEM_STOP; data->description = "Stop"; data->signal = PREPARE_FOR_SHUTDOWN; if (ck_inhibit_manager_is_shutdown_delayed (manager->priv->inhibit_manager)) { delay_time = manager->priv->system_action_idle_inhibited_delay; /* We need to keep a pointer to the system action data because * the inhibit lock can be lifted before the timeout */ manager->priv->system_action_data = data; } else { delay_time = manager->priv->system_action_idle_delay; } /* Sleep so user applications have time to respond */ manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } static gboolean dbus_stop (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); /* Check if something is blocked that action */ if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.stop-multiple-users"; } else { action = "org.freedesktop.consolekit.system.stop"; } check_system_action (manager, TRUE, context, action, do_stop); return TRUE; } static gboolean dbus_can_stop (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { #if defined HAVE_POLKIT const char *action = "org.freedesktop.consolekit.system.stop"; get_polkit_permissions (CK_MANAGER (ckmanager), action, context); #elif defined ENABLE_RBAC_SHUTDOWN if (check_rbac_permissions (CK_MANAGER (ckmanager), context, RBAC_SHUTDOWN_KEY, NULL)) { console_kit_manager_complete_can_stop (ckmanager, context, TRUE); } else { console_kit_manager_complete_can_stop (ckmanager, context, FALSE); } #else console_kit_manager_complete_can_stop (ckmanager, context, TRUE); #endif return TRUE; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.PowerOff boolean:TRUE */ static gboolean dbus_power_off (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, gboolean policykit_interactivity) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); /* Check if something is blocking that action */ if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.stop-multiple-users"; } else { action = "org.freedesktop.consolekit.system.stop"; } g_debug ("ConsoleKit PowerOff: %s", action); check_system_action (manager, policykit_interactivity, context, action, do_stop); return TRUE; } /** * dbus_can_power_off: * @ckmanager: the @ConsoleKitManager object * @context: We return a string here, either: * yes - system can and user explicitly authorized by polkit, rbac, or neither is running * no - system can and user explicitly unauthorized by polkit or rbac * challenge - system can and user requires elevation via polkit * na - system does not support it (hardware or backend support missing). * * Determines if the system can shutdown. * Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.CanPowerOff * * Returnes TRUE. **/ static gboolean dbus_can_power_off (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.stop-multiple-users"; } else { action = "org.freedesktop.consolekit.system.stop"; } check_can_action (manager, context, action); return TRUE; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.Reboot boolean:TRUE */ static gboolean dbus_reboot (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, gboolean policykit_interactivity) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); /* Check if something is blocking that action */ if (ck_inhibit_manager_is_shutdown_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.restart-multiple-users"; } else { action = "org.freedesktop.consolekit.system.restart"; } g_debug ("ConsoleKit Restart: %s", action); check_system_action (manager, policykit_interactivity, context, action, do_restart); return TRUE; } /** * dbus_can_reboot: * @ckmanager: the @ConsoleKitManager object * @context: We return a string here, either: * yes - system can and user explicitly authorized by polkit, rbac, or neither is running * no - system can and user explicitly unauthorized by polkit or rbac * challenge - system can and user requires elevation via polkit * na - system does not support it (hardware or backend support missing). * * Determines if the system can suspend. * Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.CanReboot * * Returnes TRUE. **/ static gboolean dbus_can_reboot (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.restart-multiple-users"; } else { action = "org.freedesktop.consolekit.system.restart"; } check_can_action (manager, context, action); return TRUE; } static void do_suspend (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); return; } /* Emit the signal */ console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), TRUE); /* Allocate and fill the data struct to pass to the idle cb */ data = g_new0 (SystemActionData, 1); if (data == NULL) { g_critical ("failed to allocate memory to perform suspend\n"); console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), FALSE); throw_error (context, CK_MANAGER_ERROR_FAILED, _("failed to allocate memory to perform suspend")); return; } data->manager = manager; data->context = context; data->command = LIBDIR "/ConsoleKit/scripts/ck-system-suspend"; data->event_type = CK_LOG_EVENT_SYSTEM_SUSPEND; data->description = "Suspend"; data->signal = PREPARE_FOR_SLEEP; if (ck_inhibit_manager_is_suspend_delayed (manager->priv->inhibit_manager)) { delay_time = manager->priv->system_action_idle_inhibited_delay; /* We need to keep a pointer to the system action data because * the inhibit lock can be lifted before the timeout */ manager->priv->system_action_data = data; } else { delay_time = manager->priv->system_action_idle_delay; } /* Sleep so user applications have time to respond */ manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.Suspend boolean:true */ static gboolean dbus_suspend (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, gboolean policykit_interactivity) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); /* Check if something is blocking that action */ if (ck_inhibit_manager_is_suspend_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.suspend-multiple-users"; } else { action = "org.freedesktop.consolekit.system.suspend"; } g_debug ("ConsoleKit Suspend: %s", action); check_system_action (manager, policykit_interactivity, context, action, do_suspend); return TRUE; } /** * dbus_can_suspend: * @ckmanager: the @ConsoleKitManager object * @context: We return a string here, either: * yes - system can and user explicitly authorized by polkit, rbac, or neither is running * no - system can and user explicitly unauthorized by polkit or rbac * challenge - system can and user requires elevation via polkit * na - system does not support it (hardware or backend support missing). * * Determines if the system can suspend. * Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.CanSuspend * * Returnes TRUE. **/ static gboolean dbus_can_suspend (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.suspend-multiple-users"; } else { action = "org.freedesktop.consolekit.system.suspend"; } if (ck_system_can_suspend ()) { check_can_action (manager, context, action); } else { /* not supported by system (or consolekit backend) */ console_kit_manager_complete_can_suspend (ckmanager, context, "na"); } return TRUE; } static void do_hibernate (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); return; } /* Emit the signal */ console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), TRUE); /* Allocate and fill the data struct to pass to the idle cb */ data = g_new0 (SystemActionData, 1); if (data == NULL) { g_critical ("failed to allocate memory to perform hibernate\n"); console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), FALSE); throw_error (context, CK_MANAGER_ERROR_FAILED, _("failed to allocate memory to perform hibernate")); return; } data->manager = manager; data->context = context; data->command = LIBDIR "/ConsoleKit/scripts/ck-system-hibernate"; data->event_type = CK_LOG_EVENT_SYSTEM_HIBERNATE; data->description = "Hibernate"; data->signal = PREPARE_FOR_SLEEP; if (ck_inhibit_manager_is_suspend_delayed (manager->priv->inhibit_manager)) { delay_time = manager->priv->system_action_idle_inhibited_delay; /* We need to keep a pointer to the system action data because * the inhibit lock can be lifted before the timeout */ manager->priv->system_action_data = data; } else { delay_time = manager->priv->system_action_idle_delay; } /* Sleep so user applications have time to respond */ manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.Hibernate boolean:true */ static gboolean dbus_hibernate (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, gboolean policykit_interactivity) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); /* Check if something is blocking that action */ if (ck_inhibit_manager_is_suspend_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.hibernate-multiple-users"; } else { action = "org.freedesktop.consolekit.system.hibernate"; } g_debug ("ConsoleKit Hibernate: %s", action); check_system_action (manager, policykit_interactivity, context, action, do_hibernate); return TRUE; } /** * dbus_can_hibernate: * @ckmanager: the @ConsoleKitManager object * @context: We return a string here, either: * yes - system can and user explicitly authorized by polkit, rbac, or neither is running * no - system can and user explicitly unauthorized by polkit or rbac * challenge - system can and user requires elevation via polkit * na - system does not support it (hardware or backend support missing). * * Determines if the system can hibernate. * Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.CanHibernate * * Returnes TRUE. **/ static gboolean dbus_can_hibernate (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.hibernate-multiple-users"; } else { action = "org.freedesktop.consolekit.system.hibernate"; } if (ck_system_can_hibernate ()) { check_can_action (manager, context, action); } else { /* not supported by system (or consolekit backend) */ console_kit_manager_complete_can_hibernate (ckmanager, context, "na"); } return TRUE; } static void do_hybrid_sleep (CkManager *manager, GDBusMethodInvocation *context) { SystemActionData *data; guint delay_time; /* Don't allow multiple system actions at the same time */ if (manager->priv->system_action_idle_id != 0) { throw_error (context, CK_MANAGER_ERROR_BUSY, _("Attempting to perform a system action while one is in progress")); return; } /* Emit the signal */ console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), TRUE); /* Allocate and fill the data struct to pass to the idle cb */ data = g_new0 (SystemActionData, 1); if (data == NULL) { g_critical ("failed to allocate memory to perform hybrid sleep\n"); console_kit_manager_emit_prepare_for_sleep (CONSOLE_KIT_MANAGER (manager), FALSE); throw_error (context, CK_MANAGER_ERROR_FAILED, _("failed to allocate memory to perform hybrid sleep")); return; } data->manager = manager; data->context = context; data->command = LIBDIR "/ConsoleKit/scripts/ck-system-hybridsleep"; data->event_type = CK_LOG_EVENT_SYSTEM_HIBERNATE; data->description = "Hybrid Sleep"; data->signal = PREPARE_FOR_SLEEP; if (ck_inhibit_manager_is_suspend_delayed (manager->priv->inhibit_manager)) { delay_time = manager->priv->system_action_idle_inhibited_delay; /* We need to keep a pointer to the system action data because * the inhibit lock can be lifted before the timeout */ manager->priv->system_action_data = data; } else { delay_time = manager->priv->system_action_idle_delay; } /* Sleep so user applications have time to respond */ manager->priv->system_action_idle_id = g_timeout_add (delay_time, (GSourceFunc)system_action_idle_cb, data); } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.HybridSleep boolean:true */ static gboolean dbus_hybrid_sleep (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, gboolean policykit_interactivity) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); /* Check if something is blocking that action */ if (ck_inhibit_manager_is_suspend_blocked (manager->priv->inhibit_manager)) { throw_error (context, CK_MANAGER_ERROR_INHIBITED, _("Operation is being inhibited")); return TRUE; } if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.hybridsleep-multiple-users"; } else { action = "org.freedesktop.consolekit.system.hybridsleep"; } g_debug ("ConsoleKit Hybrid Sleep: %s", action); check_system_action (manager, policykit_interactivity, context, action, do_hybrid_sleep); return TRUE; } /** * dbus_can_hybrid_sleep: * @ckmanager: the @ConsoleKitManager object * @context: We return a string here, either: * yes - system can and user explicitly authorized by polkit, rbac, or neither is running * no - system can and user explicitly unauthorized by polkit or rbac * challenge - system can and user requires elevation via polkit * na - system does not support it (hardware or backend support missing). * * Determines if the system can hybrid sleep (suspend + hibernate). * Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.CanHybridSleep * * Returnes TRUE. **/ static gboolean dbus_can_hybrid_sleep (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const char *action; TRACE (); manager = CK_MANAGER (ckmanager); if (get_system_num_users (manager) > 1) { action = "org.freedesktop.consolekit.system.hybridsleep-multiple-users"; } else { action = "org.freedesktop.consolekit.system.hybridsleep"; } if (ck_system_can_hybrid_sleep ()) { check_can_action (manager, context, action); } else { /* not supported by system (or consolekit backend) */ console_kit_manager_complete_can_hybrid_sleep (ckmanager, context, "na"); } return TRUE; } static gboolean dbus_inhibit (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, GUnixFDList *fd_list, const gchar *what, const gchar *who, const gchar *why, const gchar *mode) { CkManagerPrivate *priv; gint fd = -1; GUnixFDList *out_fd_list = NULL; const gchar *sender; uid_t uid = 0; pid_t pid = 0; gint res; TRACE (); g_return_val_if_fail (CK_IS_MANAGER (ckmanager), FALSE); priv = CK_MANAGER_GET_PRIVATE (CK_MANAGER (ckmanager)); sender = g_dbus_method_invocation_get_sender (context); res = get_caller_info (CK_MANAGER (ckmanager), sender, &uid, &pid); if (!res) { throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Error creating the inhibit lock")); return TRUE; } if (priv->inhibit_manager == NULL) { throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Inhibit manager failed to initialize")); return TRUE; } fd = ck_inhibit_manager_create_lock (priv->inhibit_manager, who, what, why, mode, uid, pid); /* if we didn't get an inhibit lock, translate and throw the error */ if (fd < 0) { switch (fd) { case CK_INHIBIT_ERROR_INVALID_INPUT: throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("Invalid input when creating inhibit lock")); return TRUE; case CK_INHIBIT_ERROR_OOM: throw_error (context, CK_MANAGER_ERROR_OOM, _("Unable to create inhibit lock, insufficient memory")); return TRUE; default: throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Error creating the inhibit lock")); return TRUE; } } out_fd_list = g_unix_fd_list_new_from_array (&fd, 1); console_kit_manager_complete_inhibit (ckmanager, context, out_fd_list, g_variant_new_handle (0)); g_clear_object (&out_fd_list); return TRUE; } /** * dbus_list_inhibitors: * @ckmanager: the @ConsoleKitManager object * @context: The GDBus context. * Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.ListInhibitors * * Returnes TRUE. **/ static gboolean dbus_list_inhibitors (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManagerPrivate *priv; GVariantBuilder inhibitor_builder; GVariant *inhibitor; GList *l, *inhibit_list; TRACE (); g_return_val_if_fail (CK_IS_MANAGER (ckmanager), FALSE); priv = CK_MANAGER_GET_PRIVATE (CK_MANAGER (ckmanager)); if (priv->inhibit_manager == NULL) { throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Inhibit manager failed to initialize")); return TRUE; } inhibit_list = ck_inhibit_manager_get_inhibit_list (priv->inhibit_manager); if (inhibit_list == NULL) { throw_error (context, CK_MANAGER_ERROR_NOTHING_INHIBITED, _("There is nothing currently inhibited")); return TRUE; } g_variant_builder_init (&inhibitor_builder, G_VARIANT_TYPE_ARRAY); for (l = inhibit_list; l != NULL; l = g_list_next (l)) { g_debug ("what %s", ck_inhibit_get_what (CK_INHIBIT (l->data))); g_debug ("who %s", ck_inhibit_get_who (CK_INHIBIT (l->data))); g_debug ("why %s", ck_inhibit_get_why (CK_INHIBIT (l->data))); g_debug ("mode %s", ck_inhibit_get_mode (CK_INHIBIT (l->data))); inhibitor = g_variant_new("(ssssuu)", ck_inhibit_get_what (CK_INHIBIT (l->data)), ck_inhibit_get_who (CK_INHIBIT (l->data)), ck_inhibit_get_why (CK_INHIBIT (l->data)), ck_inhibit_get_mode (CK_INHIBIT (l->data)), ck_inhibit_get_uid (CK_INHIBIT (l->data)), ck_inhibit_get_pid (CK_INHIBIT (l->data))); g_variant_builder_add_value (&inhibitor_builder, inhibitor); } console_kit_manager_complete_list_inhibitors(ckmanager, context, g_variant_builder_end (&inhibitor_builder)); return TRUE; } static void on_seat_active_session_changed_full (CkSeat *seat, CkSession *old_session, CkSession *session, CkManager *manager) { char *ssid = NULL; if (session != NULL) { ck_session_get_id (session, &ssid, NULL); } ck_manager_dump (manager); ck_seat_run_programs (seat, old_session, session, "seat_active_session_changed"); log_seat_active_session_changed_event (manager, seat, ssid); g_free (ssid); } static void on_seat_session_added_full (CkSeat *seat, CkSession *session, CkManager *manager) { char *ssid = NULL; ck_session_get_id (session, &ssid, NULL); ck_manager_dump (manager); ck_session_run_programs (session, "session_added"); log_seat_session_added_event (manager, seat, ssid); g_free (ssid); } static void on_seat_session_removed_full (CkSeat *seat, CkSession *session, CkManager *manager) { char *ssid = NULL; ck_session_get_id (session, &ssid, NULL); ck_manager_dump (manager); ck_session_run_programs (session, "session_removed"); log_seat_session_removed_event (manager, seat, ssid); g_free (ssid); } static void on_seat_device_added (CkSeat *seat, GVariant *device, CkManager *manager) { ck_manager_dump (manager); log_seat_device_added_event (manager, seat, device); } static void on_seat_device_removed (CkSeat *seat, GVariant *device, CkManager *manager) { ck_manager_dump (manager); log_seat_device_removed_event (manager, seat, device); } static void connect_seat_signals (CkManager *manager, CkSeat *seat) { ConsoleKitSeat *ckseat = CONSOLE_KIT_SEAT (seat); /* Private signals on CkSeat */ g_signal_connect (seat, "active-session-changed-full", G_CALLBACK (on_seat_active_session_changed_full), manager); g_signal_connect (seat, "session-added-full", G_CALLBACK (on_seat_session_added_full), manager); g_signal_connect (seat, "session-removed-full", G_CALLBACK (on_seat_session_removed_full), manager); /* Public dbus signals on ConsoleKitSeat */ g_signal_connect (ckseat, "device-added", G_CALLBACK (on_seat_device_added), manager); g_signal_connect (ckseat, "device-removed", G_CALLBACK (on_seat_device_removed), manager); } static void disconnect_seat_signals (CkManager *manager, CkSeat *seat) { ConsoleKitSeat *ckseat = CONSOLE_KIT_SEAT (seat); g_signal_handlers_disconnect_by_func (seat, on_seat_active_session_changed_full, manager); g_signal_handlers_disconnect_by_func (seat, on_seat_session_added_full, manager); g_signal_handlers_disconnect_by_func (seat, on_seat_session_removed_full, manager); g_signal_handlers_disconnect_by_func (ckseat, on_seat_device_added, manager); g_signal_handlers_disconnect_by_func (ckseat, on_seat_device_removed, manager); } static CkSeat * add_new_seat (CkManager *manager, CkSeatKind kind) { char *sid; CkSeat *seat; sid = generate_seat_id (manager); seat = ck_seat_new (sid, kind, manager->priv->connection); /* First we connect our own signals to the seat, followed by * the D-Bus signal hookup to make sure we can first dump the * database and only then send out the D-Bus signals for * it. GObject guarantees us that the signal handlers are * called in the same order as they are registered. */ connect_seat_signals (manager, seat); if (!ck_seat_register (seat)) { /* returns false if connection to bus fails */ disconnect_seat_signals (manager, seat); g_object_unref (seat); g_free (sid); return NULL; } g_hash_table_insert (manager->priv->seats, sid, seat); g_debug ("Added seat: %s kind:%d", sid, kind); ck_manager_dump (manager); ck_seat_run_programs (seat, NULL, NULL, "seat_added"); g_debug ("Emitting seat-added: %s", sid); console_kit_manager_emit_seat_added (CONSOLE_KIT_MANAGER (manager), sid); log_seat_added_event (manager, seat); return seat; } static void remove_seat (CkManager *manager, CkSeat *seat) { char *sid; char *orig_sid; CkSeat *orig_seat; gboolean res; sid = NULL; ck_seat_get_id (seat, &sid, NULL); /* Need to get the original key/value */ res = g_hash_table_lookup_extended (manager->priv->seats, sid, (gpointer *)&orig_sid, (gpointer *)&orig_seat); if (! res) { g_debug ("Seat %s is not attached", sid); goto out; } /* Remove the seat from the list but don't call * unref until the signal is emitted */ g_hash_table_steal (manager->priv->seats, sid); disconnect_seat_signals (manager, orig_seat); if (sid != NULL) { g_hash_table_remove (manager->priv->seats, sid); } ck_manager_dump (manager); ck_seat_run_programs (seat, NULL, NULL, "seat_removed"); g_debug ("Emitting seat-removed: %s", sid); console_kit_manager_emit_seat_removed (CONSOLE_KIT_MANAGER (manager), sid); log_seat_removed_event (manager, orig_seat); g_debug ("Removed seat: %s", sid); if (orig_seat != NULL) { g_object_unref (orig_seat); } g_free (orig_sid); out: g_free (sid); } #define IS_STR_SET(x) (x != NULL && x[0] != '\0') static CkSeat * find_seat_for_session (CkManager *manager, CkSession *session) { CkSeat *seat; ConsoleKitSession *cksession; gboolean is_static_x11; gboolean is_static_text; const char *display_device; const char *x11_display_device; const char *x11_display; const char *remote_host_name; guint vtnr; gboolean is_local; is_static_text = FALSE; is_static_x11 = FALSE; seat = NULL; display_device = NULL; x11_display_device = NULL; x11_display = NULL; remote_host_name = NULL; is_local = FALSE; cksession = CONSOLE_KIT_SESSION (session); /* FIXME: use matching to group entries? */ display_device = console_kit_session_get_display_device (cksession); x11_display_device = console_kit_session_get_x11_display_device (cksession); x11_display = console_kit_session_get_x11_display (cksession); remote_host_name = console_kit_session_get_remote_host_name (cksession); vtnr = console_kit_session_get_vtnr (cksession); ck_session_is_local (session, &is_local, NULL); g_debug ("find_seat_for_session vtnr returned: %d", vtnr); if (IS_STR_SET (x11_display) && IS_STR_SET (x11_display_device) && ! IS_STR_SET (remote_host_name) && is_local == TRUE) { is_static_x11 = TRUE; } else if (! IS_STR_SET (x11_display) && ! IS_STR_SET (x11_display_device) && IS_STR_SET (display_device) && ! IS_STR_SET (remote_host_name) && is_local == TRUE) { is_static_text = TRUE; } if ((is_static_x11 || is_static_text) && vtnr > 0) { char *sid; sid = g_strdup_printf ("%s/seat%u", CK_DBUS_PATH, 0); seat = g_hash_table_lookup (manager->priv->seats, sid); g_free (sid); } return seat; } static gboolean manager_set_system_idle_hint (CkManager *manager, gboolean idle_hint) { /* Check if something is blocking that action */ if (ck_inhibit_manager_is_idle_blocked (manager->priv->inhibit_manager)) { g_debug ("idle inhibited, forcing idle_hint to FALSE"); idle_hint = FALSE; } if (manager->priv->system_idle_hint != idle_hint) { manager->priv->system_idle_hint = idle_hint; /* FIXME: can we get a time from the dbus message? */ g_get_current_time (&manager->priv->system_idle_since_hint); g_debug ("Emitting system-idle-hint-changed: %d", idle_hint); console_kit_manager_emit_system_idle_hint_changed (CONSOLE_KIT_MANAGER (manager), idle_hint); } return TRUE; } static gboolean is_session_busy (char *id, CkSession *session, gpointer data) { /* return TRUE to stop search */ return !console_kit_session_get_idle_hint (CONSOLE_KIT_SESSION (session)); } static void manager_update_system_idle_hint (CkManager *manager) { CkSession *session; gboolean system_idle; /* just look for any session that doesn't have the idle-hint set */ session = g_hash_table_find (manager->priv->sessions, (GHRFunc)is_session_busy, NULL); /* if there aren't any busy sessions then the system is idle */ system_idle = (session == NULL); manager_set_system_idle_hint (manager, system_idle); } static void session_idle_hint_changed (CkSession *session, gboolean idle_hint, CkManager *manager) { manager_update_system_idle_hint (manager); } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.GetSystemIdleHint */ static gboolean dbus_get_system_idle_hint (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager = CK_MANAGER (ckmanager); TRACE (); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); console_kit_manager_complete_get_system_idle_hint (ckmanager, context, manager->priv->system_idle_hint); return TRUE; } static gboolean dbus_get_system_idle_since_hint (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager = CK_MANAGER (ckmanager); char *date_str; TRACE (); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); if (manager->priv->system_idle_hint) { date_str = g_time_val_to_iso8601 (&manager->priv->system_idle_since_hint); } else { date_str = g_strdup (""); } console_kit_manager_complete_get_system_idle_since_hint (ckmanager, context, date_str); g_free (date_str); return TRUE; } static void open_session_for_leader (CkManager *manager, CkSessionLeader *leader, const GVariant *parameters, gboolean is_local, GDBusMethodInvocation *context) { CkProcessGroup *pgroup; CkSession *session; CkSeat *seat; const char *ssid; const char *cookie; char *runtime_dir; guint unix_user; ssid = ck_session_leader_peek_session_id (leader); cookie = ck_session_leader_peek_cookie (leader); session = ck_session_new_with_parameters (ssid, cookie, parameters, manager->priv->connection); if (session == NULL) { throw_error (context, CK_MANAGER_ERROR_GENERAL, "Unable to create new session"); return; } unix_user = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION (session)); /* If the user is already logged in, continue to use the same runtime dir. * We need to do this before adding the session to the manager's table. */ runtime_dir = g_strdup (get_runtime_dir_for_user (manager, unix_user)); /* otherwise generate a new one */ if (runtime_dir == NULL) { runtime_dir = ck_generate_runtime_dir_for_user (unix_user); } g_debug ("XDG_RUNTIME_DIR is %s", runtime_dir); ck_session_set_runtime_dir (session, runtime_dir); /* If supported, add the session leader to a process group so we * can track it with something better than an environment variable */ pgroup = ck_process_group_get (); ck_process_group_create (pgroup, ck_session_leader_get_pid (leader), ssid, unix_user); g_hash_table_insert (manager->priv->sessions, g_strdup (ssid), g_object_ref (session)); /* Add to seat */ seat = find_seat_for_session (manager, session); if (seat == NULL) { /* create a new seat */ seat = add_new_seat (manager, CK_SEAT_KIND_DYNAMIC); } ck_seat_add_session (seat, session, NULL); /* set the is_local flag for the session */ g_debug ("setting session %s is_local %s", ssid, is_local ? "TRUE" : "FALSE"); ck_session_set_is_local (session, is_local, NULL); manager_update_system_idle_hint (manager); g_signal_connect (CONSOLE_KIT_SESSION (session), "idle-hint-changed", G_CALLBACK (session_idle_hint_changed), manager); /* let consumers know of the new session */ console_kit_manager_emit_session_new (CONSOLE_KIT_MANAGER (manager), ssid, ssid); g_object_unref (session); g_free (runtime_dir); g_dbus_method_invocation_return_value (context , g_variant_new ("(s)", cookie)); } static gboolean _verify_login_session_id_is_local (CkManager *manager, const char *login_session_id) { GHashTableIter iter; const char *id; CkSession *session; g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); /* If any local session exists for the given login session id then that means a trusted party has vouched for the original login */ g_debug ("Looking for local sessions for login-session-id=%s", login_session_id); session = NULL; g_hash_table_iter_init (&iter, manager->priv->sessions); while (g_hash_table_iter_next (&iter, (gpointer *)&id, (gpointer *)&session)) { if (session != NULL) { gboolean is_local; char *sessid; sessid = NULL; g_object_get (session, "login-session-id", &sessid, "is-local", &is_local, NULL); if (g_strcmp0 (sessid, login_session_id) == 0 && is_local) { g_debug ("CkManager: found is-local=true on %s", id); return TRUE; } } } return FALSE; } static void verify_and_open_session_for_leader (CkManager *manager, CkSessionLeader *leader, GVariant *parameters, GDBusMethodInvocation *context) { gboolean is_local = FALSE; GVariantIter *iter; gchar *prop_name; GVariant *value; /* Only allow a local session if originating from an existing local session. Effectively this means that only trusted parties can create local sessions. */ g_debug ("CkManager: verifying session for leader"); g_variant_get ((GVariant *)parameters, "a{sv}", &iter); while (!is_local && g_variant_iter_next (iter, "{sv}", &prop_name, &value)) { if (g_strcmp0 (prop_name, "is-local") == 0) { is_local = TRUE; } if (g_strcmp0 (prop_name, "login-session-id") == 0) { is_local = _verify_login_session_id_is_local (manager, g_variant_get_string (value, 0)); } g_free (prop_name); g_variant_unref (value); } g_variant_iter_free (iter); g_debug ("CkManager: found is-local=%s", is_local ? "true" : "false"); open_session_for_leader (manager, leader, parameters, is_local, context); } static void collect_parameters_cb (CkSessionLeader *leader, GVariant *parameters, GDBusMethodInvocation *context, CkManager *manager) { if (parameters == NULL) { throw_error (context, CK_MANAGER_ERROR_GENERAL, "Unable to get information about the calling process"); return; } verify_and_open_session_for_leader (manager, leader, parameters, context); } static void generate_session_for_leader (CkManager *manager, CkSessionLeader *leader, GDBusMethodInvocation *context) { gboolean res; res = ck_session_leader_collect_parameters (leader, context, (CkSessionLeaderDoneFunc)collect_parameters_cb, manager); if (! res) { throw_error (context, CK_MANAGER_ERROR_GENERAL, "Unable to get information about the calling process"); } } static gboolean create_session_for_sender (CkManager *manager, const char *sender, const GVariant *parameters, GDBusMethodInvocation *context) { pid_t pid = 0; uid_t uid = 0; gboolean res; char *cookie; char *ssid; CkSessionLeader *leader; g_debug ("CkManager: create session for sender: %s", sender); res = get_caller_info (manager, sender, &uid, &pid); if (! res) { g_debug ("Unable to get information about the calling process"); throw_error (context, CK_MANAGER_ERROR_GENERAL, "Unable to get information about the calling process"); return FALSE; } cookie = generate_session_cookie (manager); ssid = generate_session_id (manager); g_debug ("Creating new session ssid: %s", ssid); leader = ck_session_leader_new (); ck_session_leader_set_uid (leader, uid); ck_session_leader_set_pid (leader, pid); ck_session_leader_set_service_name (leader, sender); ck_session_leader_set_session_id (leader, ssid); ck_session_leader_set_cookie (leader, cookie); ck_session_leader_set_override_parameters (leader, parameters); /* need to store the leader info first so the pending request can be revoked */ g_hash_table_insert (manager->priv->leaders, g_strdup (cookie), g_object_ref (leader)); generate_session_for_leader (manager, leader, context); g_free (cookie); g_free (ssid); g_object_unref (leader); return TRUE; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.GetSessionForCookie string:$XDG_SESSION_COOKIE */ static gboolean dbus_get_session_for_cookie (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, const char *cookie) { CkManager *manager; gboolean res; const char *sender; uid_t calling_uid = 0; pid_t calling_pid = 0; CkProcessStat *stat; char *ssid; CkSession *session; CkSessionLeader *leader; GError *local_error; ssid = NULL; manager = CK_MANAGER (ckmanager); TRACE (); sender = g_dbus_method_invocation_get_sender (context); res = get_caller_info (manager, sender, &calling_uid, &calling_pid); if (! res) { g_debug ("CkManager: Unable to lookup caller info - failing"); throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to get information about the calling process")); return TRUE; } local_error = NULL; res = ck_process_stat_new_for_unix_pid (calling_pid, &stat, &local_error); if (! res) { if (local_error != NULL) { g_debug ("stat on pid %d failed: %s", calling_pid, local_error->message); g_clear_error (&local_error); } g_debug ("CkManager: Unable to lookup info for caller - failing"); throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to lookup information about calling process '%d'"), calling_pid); return TRUE; } /* FIXME: should we restrict this by uid? */ ck_process_stat_free (stat); leader = g_hash_table_lookup (manager->priv->leaders, cookie); if (leader == NULL) { g_debug ("CkManager: Unable to lookup cookie for caller - failing"); throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to find session for cookie")); return TRUE; } session = g_hash_table_lookup (manager->priv->sessions, ck_session_leader_peek_session_id (leader)); if (session == NULL) { g_debug ("CkManager: Unable to lookup session for cookie - failing"); throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to find session for cookie")); return TRUE; } ck_session_get_id (session, &ssid, NULL); g_debug ("CkManager: Found session '%s'", ssid); console_kit_manager_complete_get_session_for_cookie (ckmanager, context, ssid); g_free (ssid); return TRUE; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.GetSessionForUnixProcess uint32:`/sbin/pidof -s bash` */ static gboolean dbus_get_session_for_unix_process (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, guint pid) { CkManager *manager; gboolean res; const char *sender; uid_t calling_uid = 0; pid_t calling_pid = 0; char *cookie; if (pid <= 1 || pid >= UINT_MAX) { throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("pid must be > 1")); return TRUE; } manager = CK_MANAGER (ckmanager); sender = g_dbus_method_invocation_get_sender (context); TRACE (); g_debug ("pid: %u", pid); res = get_caller_info (manager, sender, &calling_uid, &calling_pid); if (! res) { throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to get information about the calling process")); return TRUE; } cookie = get_cookie_for_pid (manager, pid); if (cookie == NULL) { g_debug ("CkManager: unable to lookup session for unix process: %u", pid); throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to lookup session information for process '%d'"), pid); return TRUE; } dbus_get_session_for_cookie (ckmanager, context, cookie); g_free (cookie); return TRUE; } static gboolean dbus_get_session_by_pid (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, guint pid) { dbus_get_session_for_unix_process (ckmanager, context, pid); return TRUE; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.GetCurrentSession */ static gboolean dbus_get_current_session (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; gboolean res; const char *sender; uid_t calling_uid = 0; pid_t calling_pid = 0; TRACE (); manager = CK_MANAGER (ckmanager); sender = g_dbus_method_invocation_get_sender (context); g_debug ("CkManager: get current session"); res = get_caller_info (manager, sender, &calling_uid, &calling_pid); if (! res) { throw_error (context, CK_MANAGER_ERROR_GENERAL, _("Unable to get information about the calling process")); return TRUE; } dbus_get_session_for_unix_process (ckmanager, context, calling_pid); return TRUE; } static gboolean dbus_open_session (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { const char *sender; TRACE (); sender = g_dbus_method_invocation_get_sender (context); create_session_for_sender (CK_MANAGER (ckmanager), sender, NULL, context); return TRUE; } /* privileged method - should be protected by D-Bus policy */ static gboolean dbus_open_session_with_parameters (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, GVariant *parameters) { const char *sender; TRACE (); sender = g_dbus_method_invocation_get_sender (context); create_session_for_sender (CK_MANAGER (ckmanager), sender, parameters, context); return TRUE; } static gboolean remove_session_for_cookie (CkManager *manager, const char *cookie, CkSessionLeader *leader, GError **error) { CkSession *orig_session; char *orig_ssid; char *sid; guint unix_user; gboolean res; gboolean ret; ret = FALSE; orig_ssid = NULL; orig_session = NULL; g_debug ("Removing session for cookie: %s", cookie); if (leader == NULL) { leader = g_hash_table_lookup (manager->priv->leaders, cookie); if (leader == NULL) { g_set_error (error, CK_MANAGER_ERROR, CK_MANAGER_ERROR_GENERAL, "Unable to find session for cookie"); goto out; } } /* Need to get the original key/value */ res = g_hash_table_lookup_extended (manager->priv->sessions, ck_session_leader_peek_session_id (leader), (gpointer *)&orig_ssid, (gpointer *)&orig_session); if (! res) { g_set_error (error, CK_MANAGER_ERROR, CK_MANAGER_ERROR_GENERAL, "Unable to find session for cookie"); goto out; } /* Must keep a reference to the session in the manager until * all events for seats are cleared. So don't remove * or steal the session from the master list until * it is removed from all seats. Otherwise, event logging * for seat removals doesn't work. */ /* Get the session's uid, we'll need this if we have to remove the * runtime dir */ unix_user = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION (orig_session)); /* remove from seat */ sid = NULL; ck_session_get_seat_id (orig_session, &sid, NULL); if (sid != NULL) { CkSeat *seat; seat = g_hash_table_lookup (manager->priv->seats, sid); if (seat != NULL) { CkSeatKind kind; ck_seat_remove_session (seat, orig_session, NULL); kind = CK_SEAT_KIND_STATIC; /* if dynamic seat has no sessions then remove it */ ck_seat_get_kind (seat, &kind, NULL); if (kind == CK_SEAT_KIND_DYNAMIC) { remove_seat (manager, seat); } } } g_free (sid); /* Remove the session from the list but don't call * unref until we are done with it */ g_hash_table_steal (manager->priv->sessions, ck_session_leader_peek_session_id (leader)); ck_manager_dump (manager); manager_update_system_idle_hint (manager); /* let consumers know the session is gone */ console_kit_manager_emit_session_removed (CONSOLE_KIT_MANAGER (manager), orig_ssid, orig_ssid); if (get_runtime_dir_for_user (manager, unix_user) == NULL) { /* We removed the session and now there's no runtime dir * associated with that user. * Remove the runtime dir from the system. */ ck_remove_runtime_dir_for_user (unix_user); } ret = TRUE; out: if (orig_session != NULL) { g_object_unref (orig_session); } g_free (orig_ssid); return ret; } static gboolean paranoia_check_is_cookie_owner (CkManager *manager, const char *cookie, uid_t calling_uid, pid_t calling_pid, GError **error) { CkSessionLeader *leader; if (cookie == NULL) { g_set_error (error, CK_MANAGER_ERROR, CK_MANAGER_ERROR_GENERAL, "No cookie specified"); return FALSE; } leader = g_hash_table_lookup (manager->priv->leaders, cookie); if (leader == NULL) { g_set_error (error, CK_MANAGER_ERROR, CK_MANAGER_ERROR_GENERAL, _("Unable to find session for cookie")); return FALSE; } if (ck_session_leader_get_uid (leader) != calling_uid) { g_set_error (error, CK_MANAGER_ERROR, CK_MANAGER_ERROR_GENERAL, _("User ID does not match the owner of cookie")); return FALSE; } /* do we want to restrict to the same process? */ if (ck_session_leader_get_pid (leader) != calling_pid) { g_set_error (error, CK_MANAGER_ERROR, CK_MANAGER_ERROR_GENERAL, _("Process ID does not match the owner of cookie")); return FALSE; } return TRUE; } static gboolean dbus_close_session (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, const char *cookie) { CkManager *manager; gboolean res; const char *sender; uid_t calling_uid = 0; pid_t calling_pid = 0; GError *error; TRACE (); g_debug ("Closing session for cookie: %s", cookie); manager = CK_MANAGER (ckmanager); sender = g_dbus_method_invocation_get_sender (context); res = get_caller_info (manager, sender, &calling_uid, &calling_pid); if (! res) { throw_error (context, CK_MANAGER_ERROR_FAILED, _("Unable to lookup information about calling process '%d'"), calling_pid); return TRUE; } error = NULL; res = paranoia_check_is_cookie_owner (manager, cookie, calling_uid, calling_pid, &error); if (! res) { throw_error (context, CK_MANAGER_ERROR_FAILED, "%s", error->message); g_error_free (error); return TRUE; } error = NULL; res = remove_session_for_cookie (manager, cookie, NULL, &error); if (! res) { throw_error (context, CK_MANAGER_ERROR_FAILED, "%s", error->message); g_clear_error (&error); return TRUE; } else { g_hash_table_remove (manager->priv->leaders, cookie); } console_kit_manager_complete_close_session (ckmanager, context, TRUE); return TRUE; } typedef struct { CkManager *manager; const char *cookie; CkSessionLeader *leader; } RemoveEntity; typedef struct { const char *service_name; CkManager *manager; GPtrArray *entities; } RemoveLeaderData; static gboolean remove_leader_for_connection (const char *cookie, CkSessionLeader *leader, RemoveLeaderData *data) { const char *name; g_assert (leader != NULL); g_assert (data->service_name != NULL); name = ck_session_leader_peek_service_name (leader); if (strcmp (name, data->service_name) == 0) { RemoveEntity *entity = g_malloc(sizeof(*entity)); if (entity) { entity->manager = data->manager; entity->cookie = cookie; entity->leader = leader; g_ptr_array_add(data->entities, entity); return TRUE; } } return FALSE; } static void destroy_entity(gpointer data) { RemoveEntity *ent = data; remove_session_for_cookie (ent->manager, ent->cookie, ent->leader, NULL); ck_session_leader_cancel (ent->leader); g_object_unref(ent->leader); g_free(ent); } static void remove_sessions_for_connection (CkManager *manager, const gchar *service_name) { RemoveLeaderData data; guint n; g_debug ("Removing sessions for service name: %s", service_name); data.manager = manager; data.service_name = service_name; data.entities = g_ptr_array_new_with_free_func(destroy_entity); n = g_hash_table_foreach_steal (manager->priv->leaders, (GHRFunc)remove_leader_for_connection, &data); while (n-- > 0) { g_ptr_array_remove_index_fast (data.entities, 0); } g_assert (data.entities->len == 0); g_ptr_array_free (data.entities, TRUE); } #ifdef HAVE_POLKIT static void polkit_authority_get_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { CkManager *manager = CK_MANAGER (user_data); manager->priv->pol_ctx = polkit_authority_get_finish (res, NULL); } #endif static void on_name_owner_notify (GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) { CkManager *manager = CK_MANAGER (user_data); gchar *service_name, *old_service_name, *new_service_name; g_variant_get (parameters, "(&s&s&s)", &service_name, &old_service_name, &new_service_name); if (strlen (new_service_name) == 0) { remove_sessions_for_connection (manager, old_service_name); } } static gboolean register_manager (CkManager *manager, GDBusConnection *connection) { GError *error = NULL; manager->priv->connection = connection; #ifdef HAVE_POLKIT polkit_authority_get_async (NULL, polkit_authority_get_cb, manager); #endif if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (CONSOLE_KIT_MANAGER (manager)), manager->priv->connection, CK_MANAGER_DBUS_PATH, &error)) { if (error != NULL) { g_critical ("error exporting interface: %s", error->message); g_error_free (error); return FALSE; } } g_debug ("exported on %s", g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (CONSOLE_KIT_MANAGER (manager)))); /* connect to DBus for get_caller_info */ manager->priv->bus_proxy = g_dbus_proxy_new_sync (manager->priv->connection, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, "org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", "org.freedesktop.DBus", NULL, &error); if (manager->priv->bus_proxy == NULL) { g_warning ("cannot connect to DBus: %s", error->message); g_clear_error (&error); return FALSE; } manager->priv->name_owner_id = g_dbus_connection_signal_subscribe (manager->priv->connection, "org.freedesktop.DBus", "org.freedesktop.DBus", "NameOwnerChanged", "/org/freedesktop/DBus", NULL, G_DBUS_SIGNAL_FLAGS_NONE, on_name_owner_notify, manager, NULL); /* create the seats after we've registered on the manager on the bus */ create_seats (manager); return TRUE; } static void ck_manager_class_init (CkManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_manager_finalize; g_type_class_add_private (klass, sizeof (CkManagerPrivate)); } typedef struct { guint uid; GHashTable *hash; } GetSessionsData; static void collect_sessions_for_user (char *ssid, CkSession *session, GetSessionsData *data) { guint uid; uid = console_kit_session_get_unix_user (CONSOLE_KIT_SESSION(session)); if (uid == data->uid) { g_hash_table_add (data->hash, g_strdup (ssid)); } } static gboolean dbus_get_sessions_for_unix_user (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, guint uid) { CkManager *manager; GetSessionsData *data; const gchar **sessions; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); data = g_new0 (GetSessionsData, 1); data->uid = uid; /* Create a new hash table that we can fill with the ssids that belong to the user */ data->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_hash_table_foreach (manager->priv->sessions, (GHFunc)collect_sessions_for_user, data); /* pull out the session ids in a format gdbus likes */ sessions = (const gchar**)g_hash_table_get_keys_as_array (data->hash, NULL); /* gdbus/gvariant requires that we throw an error to return NULL */ if (sessions == NULL) { throw_error (context, CK_MANAGER_ERROR_NO_SESSIONS, _("User has no sessions")); g_hash_table_destroy (data->hash); g_free (data); return TRUE; } console_kit_manager_complete_get_sessions_for_unix_user (ckmanager, context, sessions); g_hash_table_destroy (data->hash); g_free (data); return TRUE; } /* This is deprecated */ static gboolean dbus_get_sessions_for_user (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, guint uid) { TRACE (); return dbus_get_sessions_for_unix_user (ckmanager, context, uid); } static CkSession* get_session_from_id (CkManager *manager, const gchar *arg_session_id) { gpointer session = NULL; TRACE (); g_return_val_if_fail (CK_IS_MANAGER (manager), NULL); if (arg_session_id == NULL) { return NULL; } session = g_hash_table_lookup (manager->priv->sessions, arg_session_id); if (!CK_IS_SESSION (session)) { return NULL; } return CK_SESSION (session); } static gboolean dbus_activate_session_on_seat (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, const gchar *arg_session_id, const gchar *arg_seat_id) { CkManager *manager; CkSession *session = NULL; gpointer seat = NULL; GError *error; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); session = get_session_from_id (manager, arg_session_id); if (session == NULL) { throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("Invalid session")); return TRUE; } if (arg_seat_id == NULL) { throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("Invalid seat")); return TRUE; } seat = g_hash_table_lookup (manager->priv->seats, arg_seat_id); if (!CK_IS_SEAT (seat)) { throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("Invalid seat")); return TRUE; } error = ck_seat_activate_session (seat, session, NULL); if (error != NULL) { throw_error (context, CK_MANAGER_ERROR_FAILED, error->message); g_clear_error (&error); return TRUE; } console_kit_manager_complete_activate_session_on_seat (ckmanager, context); return TRUE; } static gboolean dbus_activate_session (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, const gchar *arg_session_id) { CkManager *manager; CkSession *session = NULL; gchar *seat_id = NULL; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); session = get_session_from_id (manager, arg_session_id); if (session == NULL) { throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("Invalid session")); return TRUE; } ck_session_get_seat_id (session, &seat_id, NULL); if (seat_id == NULL) { throw_error (context, CK_MANAGER_ERROR_NO_SEATS, _("Session is not attached to a seat")); return TRUE; } dbus_activate_session_on_seat (ckmanager, context, arg_session_id, seat_id); g_free (seat_id); return TRUE; } static gboolean dbus_lock_session (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, const gchar *arg_session_id) { CkManager *manager; CkSession *session = NULL; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); session = get_session_from_id (manager, arg_session_id); if (session == NULL) { throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("Invalid session")); return TRUE; } ck_session_lock (CK_SESSION (session)); console_kit_manager_complete_lock_session (ckmanager, context); return TRUE; } static gboolean dbus_unlock_session (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context, const gchar *arg_session_id) { CkManager *manager; CkSession *session = NULL; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); session = get_session_from_id (manager, arg_session_id); if (session == NULL) { throw_error (context, CK_MANAGER_ERROR_INVALID_INPUT, _("Invalid session")); return TRUE; } ck_session_unlock (CK_SESSION (session)); console_kit_manager_complete_unlock_session (ckmanager, context); return TRUE; } static gboolean dbus_list_seats (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; GVariantBuilder seat_builder; GVariant *seat; GHashTableIter seat_iter; const gchar *key; CkSeat *value; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); /* if we don't have seats, we need to return NULL */ if (g_hash_table_size (manager->priv->seats) == 0) { throw_error (context, CK_MANAGER_ERROR_NO_SEATS, _("User has no seats")); return TRUE; } g_variant_builder_init (&seat_builder, G_VARIANT_TYPE_ARRAY); g_hash_table_iter_init (&seat_iter, manager->priv->seats); while (g_hash_table_iter_next (&seat_iter, (gpointer *)&key, (gpointer *)&value)) { seat = g_variant_new("(so)", console_kit_seat_get_name( CONSOLE_KIT_SEAT(value) ), key); g_variant_builder_add_value (&seat_builder, seat); } console_kit_manager_complete_list_seats (ckmanager, context, g_variant_builder_end (&seat_builder)); return TRUE; } static gboolean dbus_get_seats (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const gchar **seats; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); seats = (const gchar**)g_hash_table_get_keys_as_array (manager->priv->seats, NULL); /* gdbus/gvariant requires that we throw an error to return NULL */ if (seats == NULL) { throw_error (context, CK_MANAGER_ERROR_NO_SEATS, _("User has no seats")); return TRUE; } console_kit_manager_complete_get_seats (ckmanager, context, seats); g_free (seats); return TRUE; } static gboolean dbus_get_sessions (ConsoleKitManager *ckmanager, GDBusMethodInvocation *context) { CkManager *manager; const gchar **sessions; TRACE (); manager = CK_MANAGER (ckmanager); g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); sessions = (const gchar**)g_hash_table_get_keys_as_array (manager->priv->sessions, NULL); /* gdbus/gvariant requires that we throw an error to return NULL */ if (sessions == NULL) { throw_error (context, CK_MANAGER_ERROR_NO_SESSIONS, _("There are no sessions")); return TRUE; } console_kit_manager_complete_get_sessions (ckmanager, context, sessions); g_free (sessions); return TRUE; } static void add_seat_for_file (CkManager *manager, const char *filename) { char *sid; CkSeat *seat; sid = generate_seat_id (manager); seat = ck_seat_new_from_file (sid, filename, manager->priv->connection); if (seat == NULL) { return; } connect_seat_signals (manager, seat); if (!ck_seat_register (seat)) { /* returns false if connection to bus fails */ disconnect_seat_signals (manager, seat); g_object_unref (seat); g_free (sid); return; } g_hash_table_insert (manager->priv->seats, sid, seat); g_debug ("Added seat: %s", sid); ck_manager_dump (manager); ck_seat_run_programs (seat, NULL, NULL, "seat_added"); g_debug ("Emitting seat-added: %s", sid); console_kit_manager_emit_seat_added (CONSOLE_KIT_MANAGER (manager), sid); log_seat_added_event (manager, seat); } static gboolean load_seats_from_dir (CkManager *manager) { GDir *d; GError *error; const char *file; error = NULL; d = g_dir_open (CK_SEAT_DIR, 0, &error); if (d == NULL) { g_warning ("Couldn't open seat dir: %s", error->message); g_error_free (error); return FALSE; } while ((file = g_dir_read_name (d)) != NULL) { if (g_str_has_suffix (file, ".seat")) { char *path; path = g_build_filename (CK_SEAT_DIR, file, NULL); add_seat_for_file (manager, path); g_free (path); } } g_dir_close (d); return TRUE; } static void create_seats (CkManager *manager) { load_seats_from_dir (manager); } static void on_inhibit_manager_changed_event (CkInhibitManager *manager, gint inhibit_mode, gint event, gboolean enabled, gpointer user_data) { CkManagerPrivate *priv; g_return_if_fail (CK_IS_MANAGER (user_data)); priv = CK_MANAGER_GET_PRIVATE (CK_MANAGER (user_data)); /* No system action pending, return */ if (priv->system_action_idle_id == 0) { return; } /* No system action data? normal shutdown/suspend, return */ if (priv->system_action_data == NULL) { return; } /* this system action must be for a sleep or shutdown operation */ if (priv->system_action_data->signal != PREPARE_FOR_SLEEP && priv->system_action_data->signal != PREPARE_FOR_SHUTDOWN) { return; } /* the inhibit change must be for sleep or shutdown */ if (event != CK_INHIBIT_EVENT_SUSPEND && event != CK_INHIBIT_EVENT_SHUTDOWN) { return; } /* must be a delay inhibitor */ if (inhibit_mode != CK_INHIBIT_MODE_DELAY) { return; } /* the inhibit lock must be removed */ if (enabled != FALSE) { return; } /* The inhibit lock for this action was removed. * Stop the timeout and call the system action now. */ g_source_remove (priv->system_action_idle_id); priv->system_action_idle_id = 0; system_action_idle_cb (priv->system_action_data); } static void ck_manager_init (CkManager *manager) { manager->priv = CK_MANAGER_GET_PRIVATE (manager); /* reserve zero */ manager->priv->session_serial = 1; manager->priv->seat_serial = 0; manager->priv->system_idle_hint = TRUE; manager->priv->seats = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); manager->priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); manager->priv->leaders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); manager->priv->logger = ck_event_logger_new (LOG_FILE); manager->priv->inhibit_manager = ck_inhibit_manager_get (); if (manager->priv->inhibit_manager) { g_signal_connect (manager->priv->inhibit_manager, "changed-event", G_CALLBACK (on_inhibit_manager_changed_event), manager); } manager->priv->system_action_idle_delay = 2 * 1000; manager->priv->system_action_idle_inhibited_delay = 8 * 1000; manager->priv->system_action_idle_id = 0; } static void ck_manager_finalize (GObject *object) { CkManager *manager; TRACE (); g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_MANAGER (object)); manager = CK_MANAGER (object); g_return_if_fail (manager->priv != NULL); g_hash_table_destroy (manager->priv->seats); g_hash_table_destroy (manager->priv->sessions); g_hash_table_destroy (manager->priv->leaders); if (manager->priv->name_owner_id > 0 && manager->priv->connection) { g_dbus_connection_signal_unsubscribe (manager->priv->connection, manager->priv->name_owner_id); manager->priv->name_owner_id = 0; } if (manager->priv->bus_proxy != NULL) { g_object_unref (manager->priv->bus_proxy); } if (manager->priv->logger != NULL) { g_object_unref (manager->priv->logger); } if (manager->priv->inhibit_manager != NULL) { g_object_unref (manager->priv->inhibit_manager); } if (manager->priv->system_action_idle_id != 0) { g_source_remove (manager->priv->system_action_idle_id); } G_OBJECT_CLASS (ck_manager_parent_class)->finalize (object); } CkManager * ck_manager_new (GDBusConnection *connection) { if (manager_object != NULL) { g_object_ref (manager_object); } else { gboolean res; manager_object = g_object_new (CK_TYPE_MANAGER, NULL); g_object_add_weak_pointer (manager_object, (gpointer *) &manager_object); res = register_manager (manager_object, connection); if (! res) { g_object_unref (manager_object); return NULL; } } return CK_MANAGER (manager_object); } static void ck_manager_iface_init (ConsoleKitManagerIface *iface) { iface->handle_can_hibernate = dbus_can_hibernate; iface->handle_can_hybrid_sleep = dbus_can_hybrid_sleep; iface->handle_can_power_off = dbus_can_power_off; iface->handle_can_reboot = dbus_can_reboot; iface->handle_can_restart = dbus_can_restart; iface->handle_can_stop = dbus_can_stop; iface->handle_can_suspend = dbus_can_suspend; iface->handle_hibernate = dbus_hibernate; iface->handle_hybrid_sleep = dbus_hybrid_sleep; iface->handle_inhibit = dbus_inhibit; iface->handle_list_inhibitors = dbus_list_inhibitors; iface->handle_power_off = dbus_power_off; iface->handle_reboot = dbus_reboot; iface->handle_restart = dbus_restart; iface->handle_stop = dbus_stop; iface->handle_suspend = dbus_suspend; iface->handle_close_session = dbus_close_session; iface->handle_list_seats = dbus_list_seats; iface->handle_get_seats = dbus_get_seats; iface->handle_get_sessions = dbus_get_sessions; iface->handle_get_sessions_for_unix_user = dbus_get_sessions_for_unix_user; iface->handle_get_sessions_for_user = dbus_get_sessions_for_user; iface->handle_get_session_for_cookie = dbus_get_session_for_cookie; iface->handle_get_session_for_unix_process = dbus_get_session_for_unix_process; iface->handle_get_session_by_pid = dbus_get_session_by_pid; iface->handle_get_current_session = dbus_get_current_session; iface->handle_open_session = dbus_open_session; iface->handle_open_session_with_parameters = dbus_open_session_with_parameters; iface->handle_get_system_idle_hint = dbus_get_system_idle_hint; iface->handle_get_system_idle_since_hint = dbus_get_system_idle_since_hint; iface->handle_activate_session = dbus_activate_session; iface->handle_activate_session_on_seat = dbus_activate_session_on_seat; iface->handle_lock_session = dbus_lock_session; iface->handle_unlock_session = dbus_unlock_session; } consolekit2-1.2.6/src/ck-manager.h000066400000000000000000000052021446640754400167360ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_MANAGER_H #define __CK_MANAGER_H #include #include "ck-manager-generated.h" #include "ck-seat.h" G_BEGIN_DECLS #define CK_TYPE_MANAGER (ck_manager_get_type ()) #define CK_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_MANAGER, CkManager)) #define CK_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_MANAGER, CkManagerClass)) #define CK_IS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_MANAGER)) #define CK_IS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_MANAGER)) #define CK_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_MANAGER, CkManagerClass)) typedef struct CkManagerPrivate CkManagerPrivate; typedef struct { ConsoleKitManagerSkeleton parent; CkManagerPrivate *priv; } CkManager; typedef struct { ConsoleKitManagerSkeletonClass parent_class; } CkManagerClass; typedef enum { CK_MANAGER_ERROR_FAILED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_NOT_SUPPORTED, CK_MANAGER_ERROR_BUSY, CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INVALID_INPUT, CK_MANAGER_ERROR_OOM, CK_MANAGER_ERROR_NO_SEATS, CK_MANAGER_ERROR_NO_SESSIONS, CK_MANAGER_ERROR_NOTHING_INHIBITED, CK_MANAGER_NUM_ERRORS } CkManagerError; #define CK_MANAGER_ERROR ck_manager_error_quark () GQuark ck_manager_error_quark (void); GType ck_manager_error_get_type (void); GType ck_manager_get_type (void); CkManager * ck_manager_new (GDBusConnection *connection); G_END_DECLS #endif /* __CK_MANAGER_H */ consolekit2-1.2.6/src/ck-marshal.list000066400000000000000000000001521446640754400174760ustar00rootroot00000000000000VOID:UINT,STRING BOOLEAN:POINTER VOID:OBJECT,OBJECT VOID:INT,BOOLEAN VOID:INT,INT,BOOLEAN POINTER:POINTER consolekit2-1.2.6/src/ck-process-group.c000066400000000000000000000260271446640754400201370ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2015, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Note to porters, on Linux, cgroups are used here only to tag the session * leader process with a string, the ssid. In doing so, the kernel will * also tag any decendants of that process (via clone, fork, whatever) as well. * This way even if the process does things like double-forks or forgets to * pass along the XDG_SESSION_COOKIE, it and it's decendants always have * that ssid so ConsoleKit2 doesn't get confused. We don't need or use * anything else with cgroups such as resource management. */ #include "config.h" #include #include #include #include #include #ifdef HAVE_CGMANAGER #include #include #include #include #include #endif /* For TRACE */ #include "ck-sysdeps.h" #include "ck-process-group.h" #define CK_PROCESS_GROUP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_PROCESS_GROUP, CkProcessGroupPrivate)) struct CkProcessGroupPrivate { gint unused; #ifdef HAVE_CGMANAGER NihDBusProxy *cgmanager_proxy; #endif }; static void ck_process_group_finalize (GObject *object); G_DEFINE_TYPE (CkProcessGroup, ck_process_group, G_TYPE_OBJECT) #ifdef HAVE_CGMANAGER /* Ensure the warning message contains a %s to handle the actual warning * text from libnih */ static void throw_nih_warning (const gchar *warning) { NihError *nerr = nih_error_get (); if (nerr != NULL) { g_warning (warning, nerr->message); nih_free (nerr); } } #endif static gboolean ck_process_group_backend_init (CkProcessGroup *pgroup) { #ifdef HAVE_CGMANAGER DBusError dbus_error; DBusConnection *connection = NULL; TRACE (); dbus_error_init (&dbus_error); /* cgmanager uses a dbus based socket rather than running on the * system bus, nify. Let's connect to it. */ connection = dbus_connection_open_private (CGMANAGER_DBUS_PATH, &dbus_error); if (!connection) { /* TRANSLATORS: This is letting the user know that cgmanager * support was compiled in, but the cgmanager daemon isn't * running. */ g_warning (_("Failed to open connection to cgmanager. Is the cgmanager daemon running?")); dbus_error_free (&dbus_error); return FALSE; } dbus_connection_set_exit_on_disconnect (connection, FALSE); dbus_error_free (&dbus_error); pgroup->priv->cgmanager_proxy = nih_dbus_proxy_new (NULL, connection, NULL, "/org/linuxcontainers/cgmanager", NULL, NULL); dbus_connection_unref (connection); if (!pgroup->priv->cgmanager_proxy) { /* TRANSLATORS: There is an error with cgmanager, we're just * printing it out. Please ensure you keep the %s in the * string somewhere. It's the detailed error message from * cgmanager. */ throw_nih_warning (_("There was an error while initializing cgmanager, the error was: %s")); return FALSE; } #endif return TRUE; } /** * ck_process_group_get: * * Increases the reference count of the @CkProcessGroup object. * * Return value: Returns the CkProcessGroup object or * NULL on failure. Do not unref when finished. [transfer: none] **/ CkProcessGroup* ck_process_group_get (void) { static GObject *manager = NULL; if (manager == NULL) { manager = g_object_new (CK_TYPE_PROCESS_GROUP, NULL); g_object_add_weak_pointer (manager, (gpointer *) &manager); ck_process_group_backend_init (CK_PROCESS_GROUP (manager)); } return CK_PROCESS_GROUP (manager); } static void ck_process_group_class_init (CkProcessGroupClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_process_group_finalize; g_type_class_add_private (klass, sizeof (CkProcessGroupPrivate)); } static void ck_process_group_init (CkProcessGroup *pgroup) { pgroup->priv = CK_PROCESS_GROUP_GET_PRIVATE (pgroup); } static void ck_process_group_finalize (GObject *object) { #ifdef HAVE_CGMANAGER CkProcessGroupPrivate *priv = CK_PROCESS_GROUP_GET_PRIVATE (object); TRACE (); if (priv->cgmanager_proxy) { dbus_connection_flush(priv->cgmanager_proxy->connection); dbus_connection_close(priv->cgmanager_proxy->connection); nih_free(priv->cgmanager_proxy); } priv->cgmanager_proxy = NULL; #endif G_OBJECT_CLASS (ck_process_group_parent_class)->finalize (object); } /** * ck_process_group_create: * @CkProcessGroup: the pgroup object. * @process: the process to add to the new group * @ssid: the session id. * * Creates a new process group named @ssid and places @process inside it. * * Return value: TRUE on success, FALSE if process groups are unsupported * on this platform. **/ gboolean ck_process_group_create (CkProcessGroup *pgroup, pid_t process, const gchar *ssid, guint unix_user) { #ifdef HAVE_CGMANAGER CkProcessGroupPrivate *priv = CK_PROCESS_GROUP_GET_PRIVATE (pgroup); gint ret; gint32 existed; struct passwd *pwent; TRACE (); if (priv->cgmanager_proxy == NULL) { g_debug ("cgmanager_proxy == NULL"); return FALSE; } /* Create the cgroup, move the pid into it, and then tell cgmanager * to clean up the cgroup after all the processes are gone which * will happen when the user logs out. */ ret = cgmanager_create_sync (NULL, priv->cgmanager_proxy, "all", ssid, &existed); if (ret != 0) { /* TRANSLATORS: Please ensure you keep the %s in the * string somewhere. It's the detailed error message from * cgmanager. */ throw_nih_warning (_("Failed to create cgroup, the error was: %s")); return FALSE; } errno = 0; pwent = getpwuid (unix_user); if (pwent == NULL) { g_warning ("Unable to lookup UID: %s", g_strerror (errno)); return FALSE; } ret = cgmanager_chown_sync(NULL, priv->cgmanager_proxy, "all", ssid, pwent->pw_uid, pwent->pw_gid); if (ret != 0) { /* TRANSLATORS: Please ensure you keep the %s in the * string somewhere. It's the detailed error message from * cgmanager. */ throw_nih_warning (_("Failed to change owner of the new cgroup to owner of the session leader, the error was: %s")); return FALSE; } ret = cgmanager_move_pid_abs_sync (NULL, priv->cgmanager_proxy, "all", ssid, process); if (ret != 0) { NihError *nerr = nih_error_get (); nih_free (nerr); /* We failed to move the process into all the cgroups, but * we really only require the cpuacct for our internal use. * So try that as a fallback now. */ ret = cgmanager_move_pid_abs_sync (NULL, priv->cgmanager_proxy, "cpuacct", ssid, process); if (ret != 0) { /* TRANSLATORS: Please ensure you keep the %s in the * string somewhere. It's the detailed error message from * cgmanager. */ throw_nih_warning (_("Failed to move the session leader process to 'cpuacct' cgroup, the error was: %s")); } } return TRUE; #endif return FALSE; } /** * ck_process_group_get_ssid: * @CkProcessGroup: the pgroup object. * @process: the process to add to the new group * * Return value: the ssid of the pid, otherwise NULL **/ gchar* ck_process_group_get_ssid (CkProcessGroup *pgroup, pid_t process) { #ifdef HAVE_CGMANAGER CkProcessGroupPrivate *priv = CK_PROCESS_GROUP_GET_PRIVATE (pgroup); gint ret; char *nih_ssid = NULL; gchar *g_ssid = NULL; TRACE (); if (priv->cgmanager_proxy == NULL) { g_debug ("cgmanager_proxy == NULL"); return NULL; } ret = cgmanager_get_pid_cgroup_abs_sync (NULL, priv->cgmanager_proxy, "cpuacct", process, &nih_ssid); if (ret != 0) { /* TRANSLATORS: Please ensure you keep the %s in the * string somewhere. It's the detailed error message from * cgmanager. */ throw_nih_warning (_("Failed to get the session id from cgmanager, the error was: %s")); return NULL; } /* This is probably why you don't mix toolkits. So memory allocated * with nih causes corruption issues with glib, so copy + free it */ if (nih_ssid != NULL) { g_ssid = g_strdup (nih_ssid); nih_free (nih_ssid); } /* ignore the unknown/root cgroup */ if (g_strcmp0 (g_ssid, "/") == 0) { g_free (g_ssid); g_ssid = NULL; } return g_ssid; #endif return NULL; } consolekit2-1.2.6/src/ck-process-group.h000066400000000000000000000057061446640754400201450ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2015, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __CK_PROCESS_GROUP_H_ #define __CK_PROCESS_GROUP_H_ #include #define CK_TYPE_PROCESS_GROUP (ck_process_group_get_type ()) #define CK_PROCESS_GROUP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_PROCESS_GROUP, CkProcessGroup)) #define CK_PROCESS_GROUP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_PROCESS_GROUP, CkProcessGroupClass)) #define CK_IS_PROCESS_GROUP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_PROCESS_GROUP)) #define CK_IS_PROCESS_GROUP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_PROCESS_GROUP)) #define CK_PROCESS_GROUP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_PROCESS_GROUP, CkProcessGroupClass)) typedef struct CkProcessGroupPrivate CkProcessGroupPrivate; typedef struct { GObject parent; CkProcessGroupPrivate *priv; } CkProcessGroup; typedef struct { GObjectClass parent_class; } CkProcessGroupClass; GType ck_process_group_get_type (void); CkProcessGroup *ck_process_group_get (void); gboolean ck_process_group_create (CkProcessGroup *pgroup, pid_t process, const gchar *ssid, guint unix_user); gchar *ck_process_group_get_ssid (CkProcessGroup *pgroup, pid_t process); #endif /* __CK_PROCESS_GROUP_H_ */ consolekit2-1.2.6/src/ck-run-programs.c000066400000000000000000000157431446640754400177660ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 David Zeuthen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-run-programs.h" /* The number of wall-clock seconds a program is allowed to run before we kill it */ #define TIMEOUT_SECONDS 15 /* Guaranteed by POSIX; see 'man environ' for details */ extern char **environ; typedef struct { int refcount; char *path; gboolean child_is_running; guint watch_id; guint timeout_id; GPid pid; } ChildData; static ChildData * _child_data_new (void) { ChildData *cd; cd = g_new0 (ChildData, 1); cd->refcount = 1; g_debug ("Allocated ChildData %p", cd); return cd; } static ChildData * _child_data_ref (ChildData *cd) { cd->refcount++; return cd; } static void _child_data_unref (ChildData *cd) { cd->refcount--; if (cd->refcount == 0) { g_free (cd->path); g_free (cd); g_debug ("Freeing ChildData %p", cd); } } static void _child_watch (GPid pid, int status, ChildData *cd) { g_debug ("In _child_watch for pid %d", pid); g_spawn_close_pid (pid); g_source_remove (cd->timeout_id); cd->timeout_id = 0; cd->child_is_running = FALSE; _child_data_unref (cd); } static gboolean _child_timeout (ChildData *cd) { /* The program we ran timed out; this is a bug in the program */ g_warning ("The program %s didn't exit within %d seconds; killing it", cd->path, TIMEOUT_SECONDS); kill (cd->pid, SIGTERM); cd->child_is_running = FALSE; return FALSE; } /** * ck_run_programs: * @dirpath: Path to a directory containing programs to run * @action: Argument to pass to each program * @extra_env: Extra environment to pass * * Synchronously run all scripts with suffix .ck in the given * directory. */ void ck_run_programs (const char *dirpath, const char *action, char **extra_env) { GDir *dir; GError *error; const char *name; char **env_for_child; int environ_len; int extra_env_len; int n; int m; g_return_if_fail (dirpath != NULL); g_return_if_fail (action != NULL); g_debug ("Running programs in %s for action %s", dirpath, action); /* Construct an environment consisting of the existing and the given environment */ environ_len = environ != NULL ? g_strv_length (environ) : 0; extra_env_len = extra_env != NULL ? g_strv_length (extra_env) : 0; env_for_child = g_new0 (char *, environ_len + extra_env_len + 2); m = 0; for (n = 0; n < environ_len; n++) { env_for_child [m++] = g_strdup (environ[n]); } for (n = 0; n < extra_env_len; n++) { env_for_child [m++] = g_strdup (extra_env[n]); } env_for_child[m] = NULL; error = NULL; dir = g_dir_open (dirpath, 0, &error); if (dir == NULL) { /* This is unexpected; it means ConsoleKit isn't properly installed */ g_warning ("Unable to open directory %s: %s", dirpath, error->message); g_error_free (error); goto out; } while ((name = g_dir_read_name (dir)) != NULL) { char *child_argv[3]; ChildData *cd; gboolean res; if (!g_str_has_suffix (name, ".ck")) continue; child_argv[0] = g_strdup_printf ("%s/%s", dirpath, name); child_argv[1] = (char *) action; child_argv[2] = NULL; error = NULL; cd = _child_data_new (); cd->path = g_strdup (child_argv[0]); /* The ChildData instance is also unreffed in _child_watch; we only ref * it here to prevent cd from being destroyed while checking it in * the mainloop */ _child_data_ref (cd); res = g_spawn_async (NULL, child_argv, env_for_child, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &cd->pid, &error); if (! res) { /* This is unexpected; it means the program to run isn't installed correctly */ g_warning ("Unable to spawn %s: %s", child_argv[0], error->message); g_error_free (error); _child_data_unref (cd); _child_data_unref (cd); goto out_loop; } cd->child_is_running = TRUE; g_debug ("Waiting for child with pid %d", cd->pid); cd->watch_id = g_child_watch_add (cd->pid, (GChildWatchFunc)_child_watch, cd); cd->timeout_id = g_timeout_add (TIMEOUT_SECONDS * 1000, (GSourceFunc)_child_timeout, cd); /* run the mainloop; this allows the main daemon to * continue serving clients (including the program we * just launched) */ while (cd->child_is_running) { g_main_context_iteration (NULL, TRUE); } g_debug ("Done waiting for child with pid %d", cd->pid); _child_data_unref (cd); out_loop: g_free (child_argv[0]); } g_dir_close (dir); out: g_strfreev (env_for_child); } consolekit2-1.2.6/src/ck-run-programs.h000066400000000000000000000021241446640754400177600ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 David Zeuthen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_RUN_PROGRAMS_H #define __CK_RUN_PROGRAMS_H #include #include "ck-session.h" G_BEGIN_DECLS void ck_run_programs (const char *dirpath, const char *action, char **extra_env); G_END_DECLS #endif /* __CK_RUN_PROGRAMS_H */ consolekit2-1.2.6/src/ck-seat.c000066400000000000000000001443541446640754400162670ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "ck-sysdeps.h" #include "ck-seat.h" #include "ck-marshal.h" #include "ck-session.h" #include "ck-vt-monitor.h" #include "ck-run-programs.h" #define CK_SEAT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SEAT, CkSeatPrivate)) #define CK_SEAT_DBUS_NAME "org.freedesktop.ConsoleKit.Seat" #define NONULL_STRING(x) ((x) != NULL ? (x) : "") struct CkSeatPrivate { char *id; CkSeatKind kind; GHashTable *sessions; GPtrArray *devices; CkSession *active_session; CkVtMonitor *vt_monitor; GDBusConnection *connection; }; enum { ACTIVE_SESSION_CHANGED_FULL, SESSION_ADDED_FULL, /* Carries the session as CkSession for other uses */ SESSION_REMOVED_FULL, LAST_SIGNAL }; enum { PROP_0, PROP_ID, PROP_KIND, PROP_CONNECTION, }; static guint signals [LAST_SIGNAL] = { 0, }; static void ck_seat_finalize (GObject *object); static void ck_seat_iface_init (ConsoleKitSeatIface *iface); G_DEFINE_TYPE_WITH_CODE (CkSeat, ck_seat, CONSOLE_KIT_TYPE_SEAT_SKELETON, G_IMPLEMENT_INTERFACE (CONSOLE_KIT_TYPE_SEAT, ck_seat_iface_init)); static const GDBusErrorEntry ck_seat_error_entries[] = { { CK_SEAT_ERROR_GENERAL, CK_SEAT_DBUS_NAME ".Error.General" }, { CK_SEAT_ERROR_FAILED, CK_SEAT_DBUS_NAME ".Error.Failed" }, { CK_SEAT_ERROR_INSUFFICIENT_PERMISSION, CK_SEAT_DBUS_NAME ".Error.InsufficientPermission" }, { CK_SEAT_ERROR_NOT_SUPPORTED, CK_SEAT_DBUS_NAME ".Error.NotSupported" }, { CK_SEAT_ERROR_NO_ACTIVE_SESSION, CK_SEAT_DBUS_NAME ".Error.NoActiveSession" }, { CK_SEAT_ERROR_ALREADY_ACTIVE, CK_SEAT_DBUS_NAME ".Error.AlreadyActive" }, { CK_SEAT_ERROR_NO_SESSIONS, CK_SEAT_DBUS_NAME ".Error.NoSessions" }, }; GQuark ck_seat_error_quark (void) { static volatile gsize quark_volatile = 0; g_dbus_error_register_error_domain ("ck_seat_error", &quark_volatile, ck_seat_error_entries, G_N_ELEMENTS (ck_seat_error_entries)); return (GQuark) quark_volatile; } #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } GType ck_seat_error_get_type (void) { static GType etype = 0; if (etype == 0) { static const GEnumValue values[] = { ENUM_ENTRY (CK_SEAT_ERROR_FAILED, "Failed"), ENUM_ENTRY (CK_SEAT_ERROR_GENERAL, "General"), ENUM_ENTRY (CK_SEAT_ERROR_INSUFFICIENT_PERMISSION, "InsufficientPermission"), ENUM_ENTRY (CK_SEAT_ERROR_NOT_SUPPORTED, "NotSupported"), ENUM_ENTRY (CK_SEAT_ERROR_NO_ACTIVE_SESSION, "NoActiveSession"), ENUM_ENTRY (CK_SEAT_ERROR_ALREADY_ACTIVE, "AlreadyActive"), ENUM_ENTRY (CK_SEAT_ERROR_NO_SESSIONS, "NoSessions"), { 0, 0, 0 } }; g_assert (CK_SEAT_NUM_ERRORS == G_N_ELEMENTS (values) - 1); etype = g_enum_register_static ("Error", values); } return etype; } static void throw_error (GDBusMethodInvocation *context, gint error_code, const gchar *format, ...) { va_list args; gchar *message; va_start (args, format); message = g_strdup_vprintf (format, args); va_end (args); g_debug ("seat: throwing error: %s", message); g_dbus_method_invocation_return_error (context, CK_SEAT_ERROR, error_code, "%s", message); g_free (message); } GType ck_seat_kind_get_type (void) { static GType etype = 0; if (etype == 0) { static const GEnumValue values[] = { ENUM_ENTRY (CK_SEAT_KIND_STATIC, "Fixed single instance local seat"), ENUM_ENTRY (CK_SEAT_KIND_DYNAMIC, "Transient seat"), { 0, 0, 0 } }; etype = g_enum_register_static ("CkSeatKindType", values); } return etype; } gboolean ck_seat_get_active_session (CkSeat *seat, char **ssid, GError **error) { gboolean ret; char *session_id; g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); g_debug ("CkSeat: get active session"); session_id = NULL; ret = FALSE; if (seat->priv->active_session != NULL) { gboolean res; res = ck_session_get_id (seat->priv->active_session, &session_id, NULL); if (res) { ret = TRUE; } } else { g_debug ("CkSeat: seat has no active session"); } if (! ret) { g_set_error (error, CK_SEAT_ERROR, CK_SEAT_ERROR_NO_ACTIVE_SESSION, "%s", "Seat has no active session"); } else { if (ssid != NULL) { *ssid = g_strdup (session_id); } } g_free (session_id); return ret; } static gboolean dbus_get_active_session (ConsoleKitSeat *ckseat, GDBusMethodInvocation *context) { CkSeat *seat = CK_SEAT (ckseat); char *session_id = NULL; TRACE (); g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); ck_seat_get_active_session (seat, &session_id, NULL); if (session_id == NULL) { throw_error (context, CK_SEAT_ERROR_NO_ACTIVE_SESSION, "Seat has no active session"); return TRUE; } g_debug ("session_id '%s'", session_id); console_kit_seat_complete_get_active_session (ckseat, context, session_id); return TRUE; } typedef struct { gulong handler_id; CkSeat *seat; guint num; GDBusMethodInvocation *context; } ActivateData; static void activated_cb (CkVtMonitor *vt_monitor, guint num, ActivateData *adata) { if (adata->num == num) { if (adata->context != NULL) { g_dbus_method_invocation_return_value (adata->context, g_variant_new_boolean (TRUE)); } } else { if (adata->context != NULL) { throw_error (adata->context, CK_SEAT_ERROR_GENERAL, _("Another session was activated while waiting")); } } g_signal_handler_disconnect (vt_monitor, adata->handler_id); } gpointer ck_seat_activate_session (CkSeat *seat, CkSession *session, GDBusMethodInvocation *context) { gboolean res; gboolean ret; guint num; const char *device; ActivateData *adata; GError *vt_error = NULL; device = NULL; adata = NULL; ret = FALSE; TRACE (); if (!CK_IS_SEAT (seat)) { g_set_error (&vt_error, CK_SEAT_ERROR, CK_SEAT_ERROR_FAILED, _("There is no Seat to activate")); goto out; } /* for now, only support switching on static seat */ if (seat->priv->kind != CK_SEAT_KIND_STATIC) { g_set_error (&vt_error, CK_SEAT_ERROR, CK_SEAT_ERROR_NOT_SUPPORTED, _("Activation is not supported for this kind of seat")); goto out; } if (!CK_IS_SESSION (session)) { g_set_error (&vt_error, CK_SEAT_ERROR, CK_SEAT_ERROR_FAILED, _("Unknown session id")); goto out; } device = NULL; device = console_kit_session_get_x11_display_device (CONSOLE_KIT_SESSION (session)); if (device == NULL || g_strcmp0 (device, "") == 0) { device = console_kit_session_get_display_device (CONSOLE_KIT_SESSION (session)); } res = ck_get_console_num_from_device (device, &num); if (! res) { g_set_error (&vt_error, CK_SEAT_ERROR, CK_SEAT_ERROR_FAILED, _("Unable to activate session")); goto out; } adata = g_new0 (ActivateData, 1); adata->context = context; adata->seat = seat; adata->num = num; adata->handler_id = g_signal_connect_data (seat->priv->vt_monitor, "active-changed", G_CALLBACK (activated_cb), adata, (GClosureNotify)g_free, 0); g_debug ("Attempting to activate VT %u", num); if (seat->priv->active_session != session) { /* let the old session know it's about to change */ ck_session_set_active (seat->priv->active_session, FALSE, TRUE); } vt_error = NULL; ret = ck_vt_monitor_set_active (seat->priv->vt_monitor, num, &vt_error); if (! ret) { if (vt_error && vt_error->code == CK_VT_MONITOR_ERROR_ALREADY_ACTIVE) { g_debug ("Session already active, calling ck_session_set_active to ensure session is marked active"); g_clear_error (&vt_error); /* ensure the session knows it's active */ ck_session_set_active (session, TRUE, TRUE); } else { /* Change the error code for CkSeat */ if (vt_error) { vt_error->code = CK_SEAT_ERROR_FAILED; } else { g_set_error (&vt_error, CK_SEAT_ERROR, CK_SEAT_ERROR_FAILED, _("Unable to activate session")); } } g_signal_handler_disconnect (seat->priv->vt_monitor, adata->handler_id); goto out; } out: return vt_error; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Seat1 \ org.freedesktop.ConsoleKit.Seat.ActivateSession \ objpath:/org/freedesktop/ConsoleKit/Session2 */ static gboolean dbus_activate_session (ConsoleKitSeat *ckseat, GDBusMethodInvocation *context, const char *ssid) { CkSeat *seat; CkSession *session; GError *error = NULL; TRACE (); g_return_val_if_fail (CK_IS_SEAT (ckseat), FALSE); seat = CK_SEAT (ckseat); session = NULL; g_debug ("Trying to activate session: %s", ssid); if (ssid != NULL) { session = g_hash_table_lookup (seat->priv->sessions, ssid); } error = ck_seat_activate_session (seat, session, context); if (error != NULL) { throw_error (context, error->code, error->message); g_clear_error (&error); } else { console_kit_seat_complete_activate_session (ckseat, context); } return TRUE; } static gboolean find_session_by_vt (gpointer key, gpointer value, guint *vtnum) { ConsoleKitSession *cksession = CONSOLE_KIT_SESSION (value); if (console_kit_session_get_vtnr (cksession) == *vtnum) { return TRUE; } return FALSE; } static gboolean dbus_switch_to (ConsoleKitSeat *ckseat, GDBusMethodInvocation *invocation, guint arg_vtnr) { CkSeat *seat = CK_SEAT (ckseat); CkSession *session; char *ssid = NULL; TRACE (); g_return_val_if_fail (CK_IS_SEAT (ckseat), FALSE); /* See if there's a session on the seat with that vtnr and activate it */ session = g_hash_table_find (seat->priv->sessions, (GHRFunc)find_session_by_vt, &arg_vtnr); if (session != NULL) { if (ck_session_get_id (session, &ssid, NULL)) { dbus_activate_session (ckseat, invocation, ssid); g_free (ssid); return TRUE; } } /* Otherwise, if we have a VT monitor then attempt to activate the * VT that way. */ if (seat->priv->vt_monitor != NULL) { GError *error = NULL; if (ck_vt_monitor_set_active (seat->priv->vt_monitor, arg_vtnr, &error)) { console_kit_seat_complete_switch_to (ckseat, invocation); return TRUE; } throw_error (invocation, CK_SEAT_ERROR_FAILED, error->message); return TRUE; } /* The seat may not support VTs at all */ throw_error (invocation, CK_SEAT_ERROR_GENERAL, _("Unable to change VT for seat")); return TRUE; } static gboolean match_session_display_device (const char *key, CkSession *session, const char *display_device) { const char *device; gboolean ret; device = NULL; ret = FALSE; if (session == NULL) { goto out; } device = console_kit_session_get_display_device (CONSOLE_KIT_SESSION (session)); if (device != NULL && display_device != NULL && strcmp (device, display_device) == 0) { g_debug ("Matched display-device %s to %s", display_device, key); ret = TRUE; } out: return ret; } static gboolean match_session_x11_display_device (const char *key, CkSession *session, const char *x11_display_device) { const char *device; gboolean ret; device = NULL; ret = FALSE; if (session == NULL) { goto out; } device = console_kit_session_get_x11_display_device (CONSOLE_KIT_SESSION (session)); if (device != NULL && x11_display_device != NULL && strcmp (device, x11_display_device) == 0) { g_debug ("Matched x11-display-device %s to %s", x11_display_device, key); ret = TRUE; } out: return ret; } typedef struct { GHRFunc predicate; gpointer user_data; GList *list; } HashTableFindAllData; static void find_all_func (gpointer key, gpointer value, HashTableFindAllData *data) { gboolean res; res = data->predicate (key, value, data->user_data); if (res) { data->list = g_list_prepend (data->list, value); } } static GList * hash_table_find_all (GHashTable *hash_table, GHRFunc predicate, gpointer user_data) { HashTableFindAllData *data; GList *list; data = g_new0 (HashTableFindAllData, 1); data->predicate = predicate; data->user_data = user_data; g_hash_table_foreach (hash_table, (GHFunc) find_all_func, data); list = data->list; g_free (data); return list; } static GList * find_sessions_for_display_device (CkSeat *seat, const char *device) { GList *sessions; sessions = hash_table_find_all (seat->priv->sessions, (GHRFunc) match_session_display_device, (gpointer) device); return sessions; } static GList * find_sessions_for_x11_display_device (CkSeat *seat, const char *device) { GList *sessions; sessions = hash_table_find_all (seat->priv->sessions, (GHRFunc) match_session_x11_display_device, (gpointer) device); return sessions; } static int sort_sessions_by_age (CkSession *a, CkSession *b) { char *iso_a; char *iso_b; int ret; ck_session_get_creation_time (a, &iso_a, NULL); ck_session_get_creation_time (b, &iso_b, NULL); ret = strcmp (iso_a, iso_b); g_free (iso_a); g_free (iso_b); return ret; } static CkSession * find_oldest_session (GList *sessions) { sessions = g_list_sort (sessions, (GCompareFunc) sort_sessions_by_age); return sessions->data; } static CkSession * find_session_for_display_device (CkSeat *seat, const char *device) { GList *sessions; CkSession *session; sessions = find_sessions_for_x11_display_device (seat, device); if (sessions == NULL) { sessions = find_sessions_for_display_device (seat, device); } if (sessions == NULL) { return NULL; } if (g_list_length (sessions) == 1) { session = sessions->data; } else { session = find_oldest_session (sessions); } g_list_free (sessions); return session; } static void change_active_session (CkSeat *seat, CkSession *session) { char *ssid; CkSession *old_session; if (seat->priv->active_session == session) { g_debug ("ckseat: change_active_session: seat->priv->active_session == session"); /* ensure session knows it's active */ if (session != NULL) { ck_session_set_active (session, TRUE, TRUE); } return; } old_session = seat->priv->active_session; if (old_session != NULL) { char *old_ssid; ck_session_get_id (old_session, &old_ssid, NULL); g_debug ("ckseat: change_active_session: old session %s no longer active", old_ssid ? old_ssid : "(null)"); ck_session_set_active (old_session, FALSE, TRUE); } seat->priv->active_session = session; ssid = NULL; if (session != NULL) { g_object_ref (session); ck_session_get_id (session, &ssid, NULL); ck_session_set_active (session, TRUE, TRUE); } g_debug ("Active session changed: %s", ssid ? ssid : "(null)"); /* The order of signal emission matters here. The manager * dumps the database when receiving the * 'active-session-changed-full' signal and does callout * handling. dbus-glib will then send out a D-Bus on the * 'active-session-changed' signal. Since the D-Bus signal * must be sent when the database dump is finished it is * important that the '-full' signalled is emitted first. */ g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED_FULL], 0, old_session, session); if (ssid != NULL) { /* Only emit if we have a valid ssid or GDBus/GVariant gets mad */ console_kit_seat_emit_active_session_changed (CONSOLE_KIT_SEAT (seat), ssid); } if (old_session != NULL) { g_object_unref (old_session); } g_free (ssid); } static void update_active_vt (CkSeat *seat, guint num) { CkSession *session; char *device; device = ck_get_console_device_for_num (num); g_debug ("Active device: %s", device); session = find_session_for_display_device (seat, device); change_active_session (seat, session); g_free (device); } static void maybe_update_active_session (CkSeat *seat) { guint num; if (seat->priv->kind != CK_SEAT_KIND_STATIC) { return; } if (ck_vt_monitor_get_active (seat->priv->vt_monitor, &num, NULL)) { update_active_vt (seat, num); } } static gpointer session_activate (CkSession *session, GDBusMethodInvocation *context, CkSeat *seat) { TRACE (); return ck_seat_activate_session (seat, session, context); } gboolean ck_seat_remove_session (CkSeat *seat, CkSession *session, GError **error) { char *ssid; char *orig_ssid; CkSession *orig_session; gboolean res; gboolean ret; g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); ret = FALSE; ssid = NULL; ck_session_get_id (session, &ssid, NULL); /* Need to get the original key/value */ res = g_hash_table_lookup_extended (seat->priv->sessions, ssid, (gpointer *)&orig_ssid, (gpointer *)&orig_session); if (! res) { g_debug ("Session %s is not attached to seat %s", ssid, seat->priv->id); g_set_error (error, CK_SEAT_ERROR, CK_SEAT_ERROR_GENERAL, _("Session is not attached to this seat")); goto out; } g_signal_handlers_disconnect_by_func (session, session_activate, seat); /* Remove the session from the list but don't call * unref until the signal is emitted */ g_hash_table_steal (seat->priv->sessions, ssid); g_debug ("Emitting session-removed: %s", ssid); /* The order of signal emission matters here, too, for similar * reasons as for 'session-added'/'session-added-full'. See * above. */ g_signal_emit (seat, signals [SESSION_REMOVED_FULL], 0, session); console_kit_seat_emit_session_removed (CONSOLE_KIT_SEAT (seat), ssid); /* try to change the active session */ maybe_update_active_session (seat); if (orig_session != NULL) { g_object_unref (orig_session); } g_free (orig_ssid); ret = TRUE; out: g_free (ssid); return ret; } gboolean ck_seat_add_session (CkSeat *seat, CkSession *session, GError **error) { char *ssid; g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); g_return_val_if_fail (CK_IS_SESSION (session), FALSE); ck_session_get_id (session, &ssid, NULL); g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session)); ck_session_set_seat_id (session, seat->priv->id, NULL); g_signal_connect_object (session, "activate", G_CALLBACK (session_activate), seat, G_CONNECT_AFTER); /* FIXME: attach to property notify signals? */ g_debug ("Emitting added signal: %s", ssid); /* The order of signal emission matters here, too. See * above. */ g_signal_emit (seat, signals [SESSION_ADDED_FULL], 0, session); console_kit_seat_emit_session_added (CONSOLE_KIT_SEAT (seat), ssid); maybe_update_active_session (seat); g_free (ssid); return TRUE; } gboolean ck_seat_can_activate_sessions (CkSeat *seat, gboolean *can_activate, GError **error) { g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); if (can_activate != NULL) { *can_activate = (seat->priv->kind == CK_SEAT_KIND_STATIC); } return TRUE; } static gboolean dbus_can_activate_sessions (ConsoleKitSeat *ckseat, GDBusMethodInvocation *context) { CkSeat *seat = CK_SEAT (ckseat); TRACE (); g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); console_kit_seat_complete_can_activate_sessions (ckseat, context, seat->priv->kind == CK_SEAT_KIND_STATIC); return TRUE; } static gboolean ck_seat_has_device (CkSeat *seat, GVariant *device, gboolean *result, GError *error) { guint i; g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); *result = FALSE; for (i = 0; i < seat->priv->devices->len; i++) { if (g_variant_equal (g_ptr_array_index (seat->priv->devices, i), device)) { *result = TRUE; return TRUE; } } return TRUE; } static gboolean ck_seat_add_device (CkSeat *seat, GVariant *device, GError **error) { gboolean present; g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); /* FIXME: check if already present */ present = FALSE; ck_seat_has_device (seat, device, &present, NULL); if (present) { g_set_error (error, CK_SEAT_ERROR, CK_SEAT_ERROR_GENERAL, "%s", "Device already present"); return FALSE; } g_ptr_array_add (seat->priv->devices, device); g_debug ("Emitting device added signal"); console_kit_seat_emit_device_added (CONSOLE_KIT_SEAT (seat), device); return TRUE; } gboolean ck_seat_remove_device (CkSeat *seat, GValueArray *device, GError **error) { g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); /* FIXME: check if already present */ /*if (0) { g_debug ("Emitting device removed signal"); console_kit_seat_emit_device_removed (CONSOLE_KIT_SEAT (seat), device); }*/ return TRUE; } gboolean ck_seat_get_kind (CkSeat *seat, CkSeatKind *kind, GError **error) { g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); if (kind != NULL) { *kind = seat->priv->kind; } return TRUE; } gboolean ck_seat_get_id (CkSeat *seat, char **id, GError **error) { g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); if (id != NULL) { *id = g_strdup (seat->priv->id); } return TRUE; } static gboolean dbus_get_id (ConsoleKitSeat *ckseat, GDBusMethodInvocation *context) { CkSeat *seat = CK_SEAT (ckseat); TRACE (); g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); console_kit_seat_complete_get_id (ckseat, context, seat->priv->id); return TRUE; } static gboolean dbus_get_name (ConsoleKitSeat *ckseat, GDBusMethodInvocation *context) { CkSeat *seat = CK_SEAT (ckseat); TRACE (); g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); console_kit_seat_complete_get_name (ckseat, context, console_kit_seat_get_name (ckseat)); return TRUE; } static void active_vt_changed (CkVtMonitor *vt_monitor, guint num, CkSeat *seat) { g_debug ("Active vt changed: %u", num); update_active_vt (seat, num); } gboolean ck_seat_register (CkSeat *seat) { GError *error = NULL; g_debug ("register seat"); error = NULL; if (seat->priv->connection == NULL) { g_critical ("seat->priv->connection == NULL"); return FALSE; } g_debug ("exporting path %s", seat->priv->id); if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (CONSOLE_KIT_SEAT (seat)), seat->priv->connection, seat->priv->id, &error)) { if (error != NULL) { g_critical ("error exporting interface: %s", error->message); g_error_free (error); return FALSE; } } g_debug ("exported on %s", g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (CONSOLE_KIT_SEAT (seat)))); return TRUE; } static void listify_session_ids (char *id, CkSession *session, GPtrArray **array) { g_ptr_array_add (*array, g_strdup (id)); } gboolean ck_seat_get_sessions (CkSeat *seat, GPtrArray **sessions, GError **error) { g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); if (sessions == NULL) { return FALSE; } *sessions = g_ptr_array_new (); g_hash_table_foreach (seat->priv->sessions, (GHFunc)listify_session_ids, sessions); return TRUE; } static gboolean dbus_get_sessions (ConsoleKitSeat *ckseat, GDBusMethodInvocation *context) { CkSeat *seat; const gchar **sessions; TRACE (); seat = CK_SEAT (ckseat); g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); sessions = (const gchar**)g_hash_table_get_keys_as_array (seat->priv->sessions, NULL); /* gdbus/gvariant requires that we throw an error to return NULL */ if (sessions == NULL) { throw_error (context, CK_SEAT_ERROR_NO_SESSIONS, _("Seat has no sessions")); return TRUE; } console_kit_seat_complete_get_sessions (ckseat, context, sessions); g_free (sessions); return TRUE; } static void fill_variant (gpointer data, GVariantBuilder *devices) { g_variant_builder_add (devices, "(ss)", (gchar*)data); } static void copy_devices (gpointer data, GPtrArray **array) { g_ptr_array_add (*array, data); } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Seat1 \ org.freedesktop.ConsoleKit.Seat.GetDevices */ gboolean ck_seat_get_devices (CkSeat *seat, GPtrArray **devices, GError **error) { g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); if (devices == NULL) { return FALSE; } *devices = g_ptr_array_sized_new (seat->priv->devices->len); g_ptr_array_foreach (seat->priv->devices, (GFunc)copy_devices, devices); return TRUE; } static gboolean dbus_get_devices (ConsoleKitSeat *ckseat, GDBusMethodInvocation *context) { CkSeat *seat = CK_SEAT (ckseat); GVariantBuilder devices; TRACE (); g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); g_variant_builder_init (&devices, G_VARIANT_TYPE ("a(ss)")); g_ptr_array_foreach (seat->priv->devices, (GFunc)fill_variant, &devices); console_kit_seat_complete_get_devices (ckseat, context, g_variant_builder_end (&devices)); return TRUE; } static void _ck_seat_set_id (CkSeat *seat, const char *id) { g_free (seat->priv->id); seat->priv->id = g_strdup (id); } static void _ck_seat_set_kind (CkSeat *seat, CkSeatKind kind) { seat->priv->kind = kind; if (kind == CK_SEAT_KIND_STATIC) { console_kit_seat_set_name (CONSOLE_KIT_SEAT (seat), "seat0"); } else { /* FIXME: At some point we should properly map this to the * udev/devattr seat name when we do multi-seat */ gchar *sid = g_path_get_basename(seat->priv->id); console_kit_seat_set_name (CONSOLE_KIT_SEAT (seat), sid); g_free(sid); } } static void ck_seat_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { CkSeat *self; self = CK_SEAT (object); switch (prop_id) { case PROP_ID: _ck_seat_set_id (self, g_value_get_string (value)); break; case PROP_KIND: _ck_seat_set_kind (self, g_value_get_enum (value)); break; case PROP_CONNECTION: self->priv->connection = g_value_get_pointer (value); if (self->priv->connection == NULL) g_debug ("PROP_CONNECTION was NULL"); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ck_seat_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { CkSeat *self; self = CK_SEAT (object); switch (prop_id) { case PROP_ID: g_value_set_string (value, self->priv->id); break; case PROP_KIND: g_value_set_enum (value, self->priv->kind); break; case PROP_CONNECTION: g_value_set_pointer (value, self->priv->connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GObject * ck_seat_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { CkSeat *seat; seat = CK_SEAT (G_OBJECT_CLASS (ck_seat_parent_class)->constructor (type, n_construct_properties, construct_properties)); if (seat->priv->kind == CK_SEAT_KIND_STATIC) { seat->priv->vt_monitor = ck_vt_monitor_new (); g_signal_connect (seat->priv->vt_monitor, "active-changed", G_CALLBACK (active_vt_changed), seat); } return G_OBJECT (seat); } static void ck_seat_class_init (CkSeatClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->get_property = ck_seat_get_property; object_class->set_property = ck_seat_set_property; object_class->constructor = ck_seat_constructor; object_class->finalize = ck_seat_finalize; signals [ACTIVE_SESSION_CHANGED_FULL] = g_signal_new ("active-session-changed-full", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, ck_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, CK_TYPE_SESSION, CK_TYPE_SESSION); signals [SESSION_ADDED_FULL] = g_signal_new ("session-added-full", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, CK_TYPE_SESSION); signals [SESSION_REMOVED_FULL] = g_signal_new ("session-removed-full", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, CK_TYPE_SESSION); g_object_class_install_property (object_class, PROP_ID, g_param_spec_string ("id", "id", "id", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_KIND, g_param_spec_enum ("kind", "kind", "kind", CK_TYPE_SEAT_KIND, CK_SEAT_KIND_DYNAMIC, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_CONNECTION, g_param_spec_pointer ("gdbus-connection", "gdbus-connection", "gdbus-connection", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_type_class_add_private (klass, sizeof (CkSeatPrivate)); } static void ck_seat_init (CkSeat *seat) { seat->priv = CK_SEAT_GET_PRIVATE (seat); seat->priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); seat->priv->devices = g_ptr_array_new (); } static void ck_seat_finalize (GObject *object) { CkSeat *seat; g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_SEAT (object)); seat = CK_SEAT (object); g_return_if_fail (seat->priv != NULL); if (seat->priv->vt_monitor != NULL) { g_object_unref (seat->priv->vt_monitor); } if (seat->priv->active_session != NULL) { g_object_unref (seat->priv->active_session); } g_ptr_array_free (seat->priv->devices, TRUE); g_hash_table_destroy (seat->priv->sessions); g_free (seat->priv->id); G_OBJECT_CLASS (ck_seat_parent_class)->finalize (object); } static void ck_seat_iface_init (ConsoleKitSeatIface *iface) { iface->handle_activate_session = dbus_activate_session; iface->handle_can_activate_sessions = dbus_can_activate_sessions; iface->handle_get_active_session = dbus_get_active_session; iface->handle_get_devices = dbus_get_devices; iface->handle_get_id = dbus_get_id; iface->handle_get_name = dbus_get_name; iface->handle_get_sessions = dbus_get_sessions; iface->handle_switch_to = dbus_switch_to; } CkSeat * ck_seat_new (const char *sid, CkSeatKind kind, GDBusConnection *connection) { GObject *object; object = g_object_new (CK_TYPE_SEAT, "id", sid, "kind", kind, "gdbus-connection", connection, NULL); return CK_SEAT (object); } static CkSeat * ck_seat_new_with_devices (const char *sid, CkSeatKind kind, GPtrArray *devices, GDBusConnection *connection) { GObject *object; guint i; object = g_object_new (CK_TYPE_SEAT, "id", sid, "kind", kind, "gdbus-connection", connection, NULL); if (devices != NULL) { for (i = 0; i < devices->len; i++) { ck_seat_add_device (CK_SEAT (object), g_ptr_array_index (devices, i), NULL); } } return CK_SEAT (object); } CkSeat * ck_seat_new_from_file (const char *sid, const char *path, GDBusConnection *connection) { GKeyFile *key_file; gboolean res; GError *error; char *group; CkSeat *seat; gboolean hidden; GPtrArray *devices; char **device_list; gsize ndevices; gsize i; seat = NULL; key_file = g_key_file_new (); error = NULL; res = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error); if (! res) { g_warning ("Unable to load seats from file %s: %s", path, error->message); g_error_free (error); goto out; } group = g_key_file_get_start_group (key_file); if (group == NULL || strcmp (group, "Seat Entry") != 0) { g_warning ("Not a seat file: %s", path); goto out; } hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL); if (hidden) { g_debug ("Seat is hidden"); goto out; } device_list = g_key_file_get_string_list (key_file, group, "Devices", &ndevices, NULL); g_debug ("Creating seat %s with %zd devices", sid, ndevices); devices = g_ptr_array_sized_new (ndevices); for (i = 0; i < ndevices; i++) { char **split; GVariant *device_var; split = g_strsplit (device_list[i], ":", 2); if (split == NULL) { continue; } g_debug ("Adding device: %s %s", split[0], split[1]); device_var = g_variant_new ("(ss)", split[0], split[1]); g_ptr_array_add (devices, device_var); g_strfreev (split); } g_strfreev (device_list); g_free (group); seat = ck_seat_new_with_devices (sid, CK_SEAT_KIND_STATIC, devices, connection); g_ptr_array_free (devices, TRUE); out: g_key_file_free (key_file); return seat; } static void env_add_session_info (CkSession *session, const char *prefix, char **extra_env, int *n) { ConsoleKitSession *cksession; const char *s; char *c; gboolean b; guint u; if (session == NULL) { return; } cksession = CONSOLE_KIT_SESSION (session); c = NULL; if (ck_session_get_id (session, &c, NULL) && c != NULL && *c != '\0') { extra_env[(*n)++] = g_strdup_printf ("%sID=%s", prefix, c); } g_free (c); s = console_kit_session_get_session_type (cksession); if (s != NULL && *s != '\0') { extra_env[(*n)++] = g_strdup_printf ("%sTYPE=%s", prefix, s); } u = console_kit_session_get_unix_user (cksession); extra_env[(*n)++] = g_strdup_printf ("%sUSER_UID=%u", prefix, u); s = console_kit_session_get_display_device (cksession); if (s != NULL && *s != '\0') { extra_env[(*n)++] = g_strdup_printf ("%sDISPLAY_DEVICE=%s", prefix, s); } s = console_kit_session_get_x11_display_device (cksession); if (s != NULL && *s != '\0') { extra_env[(*n)++] = g_strdup_printf ("%sX11_DISPLAY_DEVICE=%s", prefix, s); } s = console_kit_session_get_x11_display (cksession); if (s != NULL && *s != '\0') { extra_env[(*n)++] = g_strdup_printf ("%sX11_DISPLAY=%s", prefix, s); } s = console_kit_session_get_remote_host_name (cksession); if (s != NULL && *s != '\0') { extra_env[(*n)++] = g_strdup_printf ("%sREMOTE_HOST_NAME=%s", prefix, s); } if (ck_session_is_local (session, &b, NULL)) { extra_env[(*n)++] = g_strdup_printf ("%sIS_LOCAL=%s", prefix, b ? "true" : "false"); } } void ck_seat_run_programs (CkSeat *seat, CkSession *old_session, CkSession *new_session, const char *action) { int n; char *extra_env[18]; /* be sure to adjust this as needed when * you add more variables to the callout's * environment */ n = 0; extra_env[n++] = g_strdup_printf ("CK_SEAT_ID=%s", seat->priv->id); /* Callout scripts/binaries should check if CK_SEAT_SESSION_ID * resp. CK_SEAT_OLD_SESSON_ID is set to figure out if there * will be an active session after the switch, or if there was * one before. At least one of those environment variables * will be set, possibly both. Only after checking these * variables the script should check for the other session * property variables. */ env_add_session_info (old_session, "CK_SEAT_OLD_SESSION_", extra_env, &n); env_add_session_info (new_session, "CK_SEAT_SESSION_", extra_env, &n); extra_env[n++] = NULL; g_assert((guint)n <= G_N_ELEMENTS(extra_env)); ck_run_programs (SYSCONFDIR "/ConsoleKit/run-seat.d", action, extra_env); ck_run_programs (LIBDIR "/ConsoleKit/run-seat.d", action, extra_env); for (n = 0; extra_env[n] != NULL; n++) { g_free (extra_env[n]); } } static void dump_seat_session_iter (char *id, CkSession *session, GString *str) { char *session_id; GError *error; error = NULL; if (! ck_session_get_id (session, &session_id, &error)) { g_warning ("Cannot get session id from seat: %s", error->message); g_error_free (error); } else { if (str->len > 0) { g_string_append_c (str, ' '); } g_string_append (str, session_id); g_free (session_id); } } void ck_seat_dump (CkSeat *seat, GKeyFile *key_file) { char *group_name; GString *str; char *s; guint n; group_name = g_strdup_printf ("Seat %s", seat->priv->id); g_key_file_set_integer (key_file, group_name, "kind", seat->priv->kind); str = g_string_new (NULL); g_hash_table_foreach (seat->priv->sessions, (GHFunc) dump_seat_session_iter, str); s = g_string_free (str, FALSE); g_key_file_set_string (key_file, group_name, "sessions", s); g_free (s); str = g_string_new (NULL); if (seat->priv->devices != NULL) { for (n = 0; n < seat->priv->devices->len; n++) { guint m; GValueArray *va; va = seat->priv->devices->pdata[n]; if (str->len > 0) g_string_append_c (str, ' '); for (m = 0; m < va->n_values; m++) { if (m > 0) g_string_append_c (str, ':'); g_string_append (str, g_value_get_string ((const GValue *) &((va->values)[m]))); } g_debug ("foo %d", va->n_values); } } s = g_string_free (str, FALSE); g_key_file_set_string (key_file, group_name, "devices", s); g_free (s); if (seat->priv->active_session != NULL) { char *session_id; GError *error; error = NULL; if (! ck_session_get_id (seat->priv->active_session, &session_id, &error)) { g_warning ("Cannot get session id for active session on seat %s: %s", seat->priv->id, error->message); g_error_free (error); } else { g_key_file_set_string (key_file, group_name, "active_session", NONULL_STRING (session_id)); g_free (session_id); } } g_free (group_name); } consolekit2-1.2.6/src/ck-seat.h000066400000000000000000000135041446640754400162640ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_SEAT_H #define __CK_SEAT_H #include #include "ck-session.h" #include "ck-seat-generated.h" G_BEGIN_DECLS #define CK_TYPE_SEAT (ck_seat_get_type ()) #define CK_SEAT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_SEAT, CkSeat)) #define CK_SEAT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_SEAT, CkSeatClass)) #define CK_IS_SEAT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_SEAT)) #define CK_IS_SEAT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_SEAT)) #define CK_SEAT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_SEAT, CkSeatClass)) typedef struct CkSeatPrivate CkSeatPrivate; typedef struct { ConsoleKitSeatSkeleton parent; CkSeatPrivate *priv; } CkSeat; typedef struct { ConsoleKitSessionSkeletonClass parent_class; } CkSeatClass; typedef enum { CK_SEAT_KIND_STATIC, CK_SEAT_KIND_DYNAMIC, } CkSeatKind; GType ck_seat_kind_get_type (void); #define CK_TYPE_SEAT_KIND (ck_seat_kind_get_type ()) typedef enum { CK_SEAT_ERROR_GENERAL, CK_SEAT_ERROR_FAILED, CK_SEAT_ERROR_INSUFFICIENT_PERMISSION, CK_SEAT_ERROR_NOT_SUPPORTED, CK_SEAT_ERROR_NO_ACTIVE_SESSION, CK_SEAT_ERROR_ALREADY_ACTIVE, CK_SEAT_ERROR_NO_SESSIONS, CK_SEAT_NUM_ERRORS } CkSeatError; #define CK_SEAT_ERROR ck_seat_error_quark () GQuark ck_seat_error_quark (void); GType ck_seat_error_get_type (void); GType ck_seat_get_type (void); CkSeat * ck_seat_new (const char *sid, CkSeatKind kind, GDBusConnection *connection); CkSeat * ck_seat_new_from_file (const char *sid, const char *path, GDBusConnection *connection); gboolean ck_seat_register (CkSeat *seat); void ck_seat_run_programs (CkSeat *seat, CkSession *old_session, CkSession *new_session, const char *action); void ck_seat_dump (CkSeat *seat, GKeyFile *key_file); gboolean ck_seat_get_kind (CkSeat *seat, CkSeatKind *kind, GError **error); gboolean ck_seat_add_session (CkSeat *seat, CkSession *session, GError **error); gboolean ck_seat_remove_session (CkSeat *seat, CkSession *session, GError **error); gboolean ck_seat_remove_device (CkSeat *seat, GValueArray *device, GError **error); /* exported methods */ gboolean ck_seat_get_id (CkSeat *seat, char **sid, GError **error); gboolean ck_seat_get_sessions (CkSeat *seat, GPtrArray **sessions, GError **error); gboolean ck_seat_get_devices (CkSeat *seat, GPtrArray **devices, GError **error); gboolean ck_seat_get_active_session (CkSeat *seat, char **ssid, GError **error); gboolean ck_seat_can_activate_sessions (CkSeat *seat, gboolean *can_activate, GError **error); gpointer ck_seat_activate_session (CkSeat *seat, CkSession *session, GDBusMethodInvocation *context); G_END_DECLS #endif /* __CK_SEAT_H */ consolekit2-1.2.6/src/ck-session-leader.c000066400000000000000000000562021446640754400202420ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006-2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "ck-session-leader.h" #include "ck-job.h" #define CK_SESSION_LEADER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SESSION_LEADER, CkSessionLeaderPrivate)) static struct { const char *name; const char *variant_type; GType gtype; } parameter_lookup[] = { { "login-session-id", "s", G_TYPE_STRING }, { "display-device", "s", G_TYPE_STRING }, { "x11-display-device", "s", G_TYPE_STRING }, { "x11-display", "s", G_TYPE_STRING }, { "remote-host-name", "s", G_TYPE_STRING }, { "session-type", "s", G_TYPE_STRING }, { "session-class", "s", G_TYPE_STRING }, { "session-service", "s", G_TYPE_STRING }, { "is-local", "b", G_TYPE_BOOLEAN }, { "unix-user", "i", G_TYPE_INT }, { "user", "i", G_TYPE_INT }, { "vtnr", "u", G_TYPE_UINT }, }; struct CkSessionLeaderPrivate { char *id; uid_t uid; pid_t pid; char *service_name; char *session_id; char *cookie; char *runtime_dir; GList *pending_jobs; gboolean cancelled; GHashTable *override_parameters; }; enum { PROP_0, }; static void ck_session_leader_finalize (GObject *object); G_DEFINE_TYPE (CkSessionLeader, ck_session_leader, G_TYPE_OBJECT) GQuark ck_session_leader_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("ck_session_leader_error"); } return ret; } static void remove_pending_job (CkJob *job) { if (job != NULL) { char *command; command = NULL; ck_job_get_command (job, &command); g_debug ("Removing pending job: %s", command); g_free (command); ck_job_cancel (job); g_object_unref (job); } } void ck_session_leader_cancel (CkSessionLeader *leader) { g_return_if_fail (CK_IS_SESSION_LEADER (leader)); if (leader->priv->pending_jobs != NULL) { g_list_foreach (leader->priv->pending_jobs, (GFunc)remove_pending_job, NULL); g_list_free (leader->priv->pending_jobs); leader->priv->pending_jobs = NULL; } leader->priv->cancelled = TRUE; } static gboolean have_override_parameter (CkSessionLeader *leader, const char *prop_name) { gpointer data; if (leader->priv->override_parameters == NULL) { return FALSE; } if (prop_name == NULL) { return FALSE; } data = g_hash_table_lookup (leader->priv->override_parameters, prop_name); if (data == NULL) { return FALSE; } return TRUE; } static void lookup_parameter_type (const char *name, const char **variant_type, GType *gtype) { guint i; *gtype = G_TYPE_INVALID; for (i = 0; i < G_N_ELEMENTS (parameter_lookup); i++) { if (strcmp (name, parameter_lookup[i].name) == 0) { *variant_type = parameter_lookup[i].variant_type; *gtype = parameter_lookup[i].gtype; return; } } } static void add_to_parameters (gpointer key, gpointer data, GVariantBuilder *ck_parameters) { g_variant_builder_add (ck_parameters, "{sv}", key, (GVariant*) data); } /* Allocates and returns a GVariantBuilder holding all the parameters, * free with g_variant_builder_unref when done using it */ static GVariant * parse_output (CkSessionLeader *leader, const char *output) { GVariantBuilder ck_parameters; char **lines; int i; lines = g_strsplit (output, "\n", -1); if (lines == NULL) { return NULL; } g_variant_builder_init (&ck_parameters, G_VARIANT_TYPE ("a{sv}")); /* first add generated params */ for (i = 0; lines[i] != NULL; i++) { char **vals; const char *variant_type; GVariant *element; GType gtype; glong untrusted_int; gboolean is_local = FALSE; vals = g_strsplit (lines[i], " = ", 2); if (vals == NULL || vals[0] == NULL) { g_strfreev (vals); continue; } g_debug ("looking at prop %s", vals[0]); /* we're going to override this anyway so just shortcut out */ if (have_override_parameter (leader, vals[0])) { g_debug ("skipping, we're going to override it"); g_strfreev (vals); continue; } lookup_parameter_type (vals[0], &variant_type, >ype); if (gtype == G_TYPE_INVALID) { g_warning ("invalid parameter type\n"); continue; } switch (gtype) { case G_TYPE_STRING: g_debug ("creating string"); element = g_variant_new (variant_type, vals[1]); break; case G_TYPE_BOOLEAN: g_debug ("creating boolean"); if(g_ascii_strncasecmp (vals[1], "TRUE", 4) == 0) { is_local = TRUE; } element = g_variant_new (variant_type, is_local); break; case G_TYPE_INT: g_debug ("creating int"); untrusted_int = strtol (vals[1], NULL, 10); /* Error checking for untrusted input */ if ((errno == ERANGE && (untrusted_int == LONG_MAX || untrusted_int == LONG_MIN)) || (errno != 0 && untrusted_int == 0)) { g_debug ("skipping: out of range, ERANGE"); continue; } /* Sanity checks */ if (untrusted_int > INT_MAX) { g_debug ("skipping: out of range, INT_MAX"); continue; } if (untrusted_int < 0) { g_debug ("skipping: out of range, negative"); continue; } element = g_variant_new (variant_type, (uid_t)untrusted_int); break; case G_TYPE_UINT: g_debug ("creating uint"); untrusted_int = strtol (vals[1], NULL, 10); /* Error checking for untrusted input */ if ((errno == ERANGE && (untrusted_int == LONG_MAX || untrusted_int == LONG_MIN)) || (errno != 0 && untrusted_int == 0)) { g_debug ("skipping: out of range, ERANGE"); continue; } /* Sanity checks */ if (untrusted_int > G_MAXUINT) { g_debug ("skipping: out of range, G_MAXUINT"); continue; } if (untrusted_int < 0) { g_debug ("skipping: out of range, negative"); continue; } element = g_variant_new (variant_type, (guint)untrusted_int); break; default: g_warning ("ck-session-leader unsupported type"); continue; } g_variant_builder_add (&ck_parameters, "{sv}", vals[0], element); g_strfreev (vals); } g_strfreev (lines); /* now overlay the overrides */ g_hash_table_foreach (leader->priv->override_parameters, (GHFunc)add_to_parameters, &ck_parameters); return g_variant_builder_end (&ck_parameters); } static void save_parameters (CkSessionLeader *leader, const GVariant *parameters) { GVariantIter *iter; gchar *prop_name; GVariant *value; g_variant_get ((GVariant *)parameters, "a(sv)", &iter); while (g_variant_iter_next (iter, "(sv)", &prop_name, &value)) { /* filter out the nulls? - sure why not */ if (value != NULL) { const char *variant_type; GType gtype; if (prop_name == NULL) { g_debug ("Skipping NULL parameter"); g_variant_unref (value); continue; } if (strcmp (prop_name, "id") == 0 || strcmp (prop_name, "cookie") == 0) { g_debug ("Skipping restricted parameter: %s", prop_name); g_free (prop_name); g_variant_unref (value); continue; } lookup_parameter_type (prop_name, &variant_type, >ype); if (gtype == G_TYPE_INVALID) { g_debug ("Unable to extract parameter input"); g_free (prop_name); g_variant_unref (value); continue; } /* Convert legacy user property to unix-user */ if (g_strcmp0 (prop_name, "user") == 0) { g_free (prop_name); prop_name = g_strdup ("unix-user"); } g_debug ("Setting override parameters for: %s", prop_name); /* takes ownership */ g_hash_table_insert (leader->priv->override_parameters, prop_name, value); } } g_variant_iter_free (iter); } typedef struct { CkSessionLeader *leader; CkSessionLeaderDoneFunc done_cb; gpointer user_data; GDBusMethodInvocation *context; } JobData; static void job_completed (CkJob *job, int status, JobData *data) { g_debug ("Job status: %d", status); if (status == 0) { char *output; GVariant *parameters; output = NULL; ck_job_get_stdout (job, &output); g_debug ("Job output: %s", output); parameters = g_variant_ref_sink(parse_output (data->leader, output)); g_free (output); data->done_cb (data->leader, parameters, data->context, data->user_data); g_variant_unref(parameters); } else { data->done_cb (data->leader, NULL, data->context, data->user_data); } /* remove job from queue */ data->leader->priv->pending_jobs = g_list_remove (data->leader->priv->pending_jobs, job); g_signal_handlers_disconnect_by_func (job, job_completed, data); g_object_unref (job); } static void job_data_free (JobData *data) { g_object_unref (data->leader); g_free (data); } gboolean ck_session_leader_collect_parameters (CkSessionLeader *session_leader, GDBusMethodInvocation *context, CkSessionLeaderDoneFunc done_cb, gpointer user_data) { GError *local_error; char *command; gboolean res; gboolean ret; CkJob *job; JobData *data; const gchar *x11_display_device = NULL; ret = FALSE; data = g_new0 (JobData, 1); data->leader = g_object_ref (session_leader); data->done_cb = done_cb; data->user_data = user_data; data->context = context; if (have_override_parameter (session_leader, "x11-display-device")) { GVariant *var = g_hash_table_lookup (session_leader->priv->override_parameters, "x11-display-device"); x11_display_device = g_variant_get_string (var, NULL); } if (x11_display_device != NULL && g_strcmp0 (x11_display_device, "") != 0) { command = g_strdup_printf ("%s --uid %u --pid %u --x11-display-device %s", LIBEXECDIR "/ck-collect-session-info", session_leader->priv->uid, session_leader->priv->pid, x11_display_device); } else { command = g_strdup_printf ("%s --uid %u --pid %u", LIBEXECDIR "/ck-collect-session-info", session_leader->priv->uid, session_leader->priv->pid); } job = ck_job_new (); ck_job_set_command (job, command); g_free (command); g_signal_connect_data (job, "completed", G_CALLBACK (job_completed), data, (GClosureNotify)job_data_free, 0); local_error = NULL; res = ck_job_execute (job, &local_error); if (! res) { if (local_error != NULL) { g_debug ("stat on pid %d failed: %s", session_leader->priv->pid, local_error->message); g_error_free (local_error); } g_object_unref (job); goto out; } /* Add job to queue */ session_leader->priv->pending_jobs = g_list_prepend (session_leader->priv->pending_jobs, job); ret = TRUE; out: return ret; } const char * ck_session_leader_peek_session_id (CkSessionLeader *session_leader) { g_return_val_if_fail (CK_IS_SESSION_LEADER (session_leader), NULL); return session_leader->priv->session_id; } const char * ck_session_leader_peek_cookie (CkSessionLeader *session_leader) { g_return_val_if_fail (CK_IS_SESSION_LEADER (session_leader), NULL); return session_leader->priv->cookie; } const char * ck_session_leader_peek_service_name (CkSessionLeader *session_leader) { g_return_val_if_fail (CK_IS_SESSION_LEADER (session_leader), NULL); return session_leader->priv->service_name; } uid_t ck_session_leader_get_uid (CkSessionLeader *session_leader) { g_return_val_if_fail (CK_IS_SESSION_LEADER (session_leader), -1); return session_leader->priv->uid; } pid_t ck_session_leader_get_pid (CkSessionLeader *session_leader) { g_return_val_if_fail (CK_IS_SESSION_LEADER (session_leader), -1); return session_leader->priv->pid; } void ck_session_leader_set_pid (CkSessionLeader *session_leader, pid_t pid) { g_return_if_fail (CK_IS_SESSION_LEADER (session_leader)); session_leader->priv->pid = pid; } void ck_session_leader_set_uid (CkSessionLeader *session_leader, uid_t uid) { g_return_if_fail (CK_IS_SESSION_LEADER (session_leader)); session_leader->priv->uid = uid; } void ck_session_leader_set_session_id (CkSessionLeader *session_leader, const char *session_id) { g_return_if_fail (CK_IS_SESSION_LEADER (session_leader)); g_free (session_leader->priv->session_id); session_leader->priv->session_id = g_strdup (session_id); } void ck_session_leader_set_cookie (CkSessionLeader *session_leader, const char *cookie) { g_return_if_fail (CK_IS_SESSION_LEADER (session_leader)); g_free (session_leader->priv->cookie); session_leader->priv->cookie = g_strdup (cookie); } void ck_session_leader_set_service_name (CkSessionLeader *session_leader, const char *service_name) { g_return_if_fail (CK_IS_SESSION_LEADER (session_leader)); g_free (session_leader->priv->service_name); session_leader->priv->service_name = g_strdup (service_name); } void ck_session_leader_set_override_parameters (CkSessionLeader *session_leader, const GVariant *parameters) { g_return_if_fail (CK_IS_SESSION_LEADER (session_leader)); if (session_leader->priv->override_parameters != NULL) { g_hash_table_remove_all (session_leader->priv->override_parameters); } if (parameters != NULL) { save_parameters (session_leader, parameters); } } static void ck_session_leader_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ck_session_leader_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GObject * ck_session_leader_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { CkSessionLeader *session_leader; session_leader = CK_SESSION_LEADER (G_OBJECT_CLASS (ck_session_leader_parent_class)->constructor (type, n_construct_properties, construct_properties)); return G_OBJECT (session_leader); } static void ck_session_leader_class_init (CkSessionLeaderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = ck_session_leader_constructor; object_class->get_property = ck_session_leader_get_property; object_class->set_property = ck_session_leader_set_property; object_class->finalize = ck_session_leader_finalize; g_type_class_add_private (klass, sizeof (CkSessionLeaderPrivate)); } static void parameter_free (gpointer data) { g_variant_unref ((GVariant*)data); } static void ck_session_leader_init (CkSessionLeader *session_leader) { session_leader->priv = CK_SESSION_LEADER_GET_PRIVATE (session_leader); session_leader->priv->override_parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)parameter_free); } static void ck_session_leader_finalize (GObject *object) { CkSessionLeader *session_leader; g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_SESSION_LEADER (object)); session_leader = CK_SESSION_LEADER (object); g_return_if_fail (session_leader->priv != NULL); g_free (session_leader->priv->session_id); session_leader->priv->session_id = NULL; g_free (session_leader->priv->cookie); session_leader->priv->cookie = NULL; g_free (session_leader->priv->service_name); session_leader->priv->service_name = NULL; g_hash_table_destroy (session_leader->priv->override_parameters); G_OBJECT_CLASS (ck_session_leader_parent_class)->finalize (object); } CkSessionLeader * ck_session_leader_new (void) { GObject *object; object = g_object_new (CK_TYPE_SESSION_LEADER, NULL); return CK_SESSION_LEADER (object); } void ck_session_leader_dump (CkSessionLeader *session_leader, GKeyFile *key_file) { char *group_name; group_name = g_strdup_printf ("SessionLeader %s", session_leader->priv->session_id); g_key_file_set_string (key_file, group_name, "session", session_leader->priv->session_id); g_key_file_set_integer (key_file, group_name, "uid", session_leader->priv->uid); g_key_file_set_integer (key_file, group_name, "pid", session_leader->priv->pid); g_key_file_set_string (key_file, group_name, "service_name", session_leader->priv->service_name); g_free (group_name); } consolekit2-1.2.6/src/ck-session-leader.h000066400000000000000000000116031446640754400202430ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006-2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_SESSION_LEADER_H #define __CK_SESSION_LEADER_H #include #include G_BEGIN_DECLS #define CK_TYPE_SESSION_LEADER (ck_session_leader_get_type ()) #define CK_SESSION_LEADER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_SESSION_LEADER, CkSessionLeader)) #define CK_SESSION_LEADER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_SESSION_LEADER, CkSessionLeaderClass)) #define CK_IS_SESSION_LEADER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_SESSION_LEADER)) #define CK_IS_SESSION_LEADER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_SESSION_LEADER)) #define CK_SESSION_LEADER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_SESSION_LEADER, CkSessionLeaderClass)) typedef struct CkSessionLeaderPrivate CkSessionLeaderPrivate; typedef struct { GObject parent; CkSessionLeaderPrivate *priv; } CkSessionLeader; typedef struct { GObjectClass parent_class; } CkSessionLeaderClass; typedef enum { CK_SESSION_LEADER_ERROR_GENERAL } CkSessionLeaderError; #define CK_SESSION_LEADER_ERROR ck_session_leader_error_quark () typedef void (* CkSessionLeaderDoneFunc) (CkSessionLeader *session_leader, GVariant *parameters, GDBusMethodInvocation *context, gpointer data); GQuark ck_session_leader_error_quark (void); GType ck_session_leader_get_type (void); CkSessionLeader * ck_session_leader_new (void); void ck_session_leader_set_pid (CkSessionLeader *session_leader, pid_t pid); void ck_session_leader_set_uid (CkSessionLeader *session_leader, uid_t uid); void ck_session_leader_set_session_id (CkSessionLeader *session_leader, const char *session_id); void ck_session_leader_set_cookie (CkSessionLeader *session_leader, const char *cookie); void ck_session_leader_set_service_name (CkSessionLeader *session_leader, const char *sender); void ck_session_leader_set_override_parameters (CkSessionLeader *session_leader, const GVariant *parameters); const char * ck_session_leader_peek_session_id (CkSessionLeader *session_leader); const char * ck_session_leader_peek_cookie (CkSessionLeader *session_leader); const char * ck_session_leader_peek_service_name (CkSessionLeader *session_leader); uid_t ck_session_leader_get_uid (CkSessionLeader *session_leader); pid_t ck_session_leader_get_pid (CkSessionLeader *session_leader); gboolean ck_session_leader_collect_parameters (CkSessionLeader *session_leader, GDBusMethodInvocation *context, CkSessionLeaderDoneFunc done_cb, gpointer data); void ck_session_leader_cancel (CkSessionLeader *session_leader); void ck_session_leader_dump (CkSessionLeader *session_leader, GKeyFile *key_file); G_END_DECLS #endif /* __CK_SESSION_LEADER_H */ consolekit2-1.2.6/src/ck-session.c000066400000000000000000002454431446640754400170170ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006-2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_VT_H #include #endif #ifdef HAVE_SYS_KD_H #include #endif #ifdef HAVE_SYS_CONSIO_H #include #endif #ifdef HAVE_SYS_KBIO_H #include #endif #ifdef HAVE_DEV_WSCONS_WSCONSIO_H #include #endif #ifdef HAVE_DEV_WSCONS_WSDISPLAY_USL_IO_H #include #endif #include #include #include #include #include #include #include "ck-tty-idle-monitor.h" #include "ck-session.h" #include "ck-seat.h" #include "ck-marshal.h" #include "ck-run-programs.h" #include "ck-sysdeps.h" #include "ck-device.h" #define CK_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SESSION, CkSessionPrivate)) #define CK_SESSION_DBUS_NAME "org.freedesktop.ConsoleKit.Session" #define NONULL_STRING(x) ((x) != NULL ? (x) : "") #define IDLE_TIME_SECS 60 #ifndef KDSKBMUTE #define KDSKBMUTE 0x4B51 #endif #ifdef K_OFF #define KBD_OFF_MODE K_OFF #else #define KBD_OFF_MODE K_RAW #endif struct CkSessionPrivate { char *id; char *cookie; char *seat_id; char *runtime_dir; char *login_session_id; gchar *session_controller; guint session_controller_watchid; GList *devices; guint pause_devices_timer; gint tty_fd; gint old_kbd_mode; guint sig_watch_s1; guint sig_watch_s2; GTimeVal creation_time; CkTtyIdleMonitor *idle_monitor; GTimeVal idle_since_hint; GDBusConnection *connection; GDBusProxy *bus_proxy; }; enum { ACTIVATE, LAST_SIGNAL }; /* Private properties not exported over D-BUS */ enum { PROP_0, PROP_ID, PROP_COOKIE, PROP_LOGIN_SESSION_ID, PROP_SESSION_CONTROLLER, }; static guint signals [LAST_SIGNAL] = { 0, }; static void ck_session_iface_init (ConsoleKitSessionIface *iface); static void ck_session_finalize (GObject *object); static void ck_session_remove_all_devices (CkSession *session); G_DEFINE_TYPE_WITH_CODE (CkSession, ck_session, CONSOLE_KIT_TYPE_SESSION_SKELETON, G_IMPLEMENT_INTERFACE (CONSOLE_KIT_TYPE_SESSION, ck_session_iface_init)); static const GDBusErrorEntry ck_session_error_entries[] = { { CK_SESSION_ERROR_FAILED, CK_SESSION_DBUS_NAME ".Error.Failed" }, { CK_SESSION_ERROR_GENERAL, CK_SESSION_DBUS_NAME ".Error.General" }, { CK_SESSION_ERROR_INSUFFICIENT_PERMISSION, CK_SESSION_DBUS_NAME ".Error.InsufficientPermission" }, { CK_SESSION_ERROR_NOT_SUPPORTED, CK_SESSION_DBUS_NAME ".Error.NotSupported" }, { CK_SESSION_ERROR_ALREADY_ACTIVE, CK_SESSION_DBUS_NAME ".Error.AlreadyActive" } }; GQuark ck_session_error_quark (void) { static volatile gsize quark_volatile = 0; g_dbus_error_register_error_domain ("ck_session_error", &quark_volatile, ck_session_error_entries, G_N_ELEMENTS (ck_session_error_entries)); return (GQuark) quark_volatile; } #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } GType ck_session_error_get_type (void) { static GType etype = 0; if (etype == 0) { static const GEnumValue values[] = { ENUM_ENTRY (CK_SESSION_ERROR_FAILED, "Failed"), ENUM_ENTRY (CK_SESSION_ERROR_GENERAL, "General"), ENUM_ENTRY (CK_SESSION_ERROR_INSUFFICIENT_PERMISSION, "InsufficientPermission"), ENUM_ENTRY (CK_SESSION_ERROR_NOT_SUPPORTED, "NotSupported"), ENUM_ENTRY (CK_SESSION_ERROR_ALREADY_ACTIVE, "AlreadyActive"), { 0, 0, 0 } }; g_assert (CK_SESSION_NUM_ERRORS == G_N_ELEMENTS (values) - 1); etype = g_enum_register_static ("Error", values); } return etype; } static void throw_error (GDBusMethodInvocation *context, gint error_code, const gchar *format, ...) { va_list args; gchar *message; va_start (args, format); message = g_strdup_vprintf (format, args); va_end (args); g_debug ("session: throwing error: %s", message); g_dbus_method_invocation_return_error (context, CK_SESSION_ERROR, error_code, "%s", message); g_free (message); } static gboolean register_session (CkSession *session, GDBusConnection *connection) { GError *error = NULL; g_debug ("register session"); error = NULL; if (connection == NULL) { g_critical ("CkSession-register_session:connection == NULL"); } else { session->priv->connection = connection; } if (session->priv->connection == NULL) { if (error != NULL) { g_critical ("error getting system bus: %s", error->message); g_error_free (error); } return FALSE; } g_debug ("exporting path %s", session->priv->id); if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (CONSOLE_KIT_SESSION (session)), session->priv->connection, session->priv->id, &error)) { if (error != NULL) { g_critical ("error exporting interface: %s", error->message); g_error_free (error); return FALSE; } } g_debug ("exported on %s", g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (CONSOLE_KIT_SESSION (session)))); /* connect to DBus for get_caller_info */ session->priv->bus_proxy = g_dbus_proxy_new_sync (session->priv->connection, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, NULL, "org.freedesktop.DBus", "/org/freedesktop/DBus/Bus", "org.freedesktop.DBus", NULL, &error); if (session->priv->bus_proxy == NULL) { g_warning ("cannot connect to DBus: %s", error->message); g_error_free (error); } /* default to unspecified for the session type on startup */ if (console_kit_session_get_session_type (CONSOLE_KIT_SESSION (session)) == NULL) { console_kit_session_set_session_type (CONSOLE_KIT_SESSION (session), "unspecified"); } /* default to unspecified for the session service on startup */ if (console_kit_session_get_session_service (CONSOLE_KIT_SESSION (session)) == NULL) { console_kit_session_set_session_service (CONSOLE_KIT_SESSION (session), "unspecified"); } /* default to user for the session class on startup */ if (console_kit_session_get_session_class (CONSOLE_KIT_SESSION (session)) == NULL) { console_kit_session_set_session_class (CONSOLE_KIT_SESSION (session), "user"); } /* default to online for the session state on startup */ if (console_kit_session_get_session_class (CONSOLE_KIT_SESSION (session)) == NULL) { console_kit_session_set_session_class (CONSOLE_KIT_SESSION (session), "online"); } return TRUE; } /* lock and unlock are separate functions because we may want security policy to be handled separately */ void ck_session_lock (CkSession *session) { ConsoleKitSession *cksession; TRACE (); g_return_if_fail (CK_IS_SESSION (session)); cksession = CONSOLE_KIT_SESSION (session); g_debug ("Emitting lock for session %s", session->priv->id); console_kit_session_set_locked_hint (cksession, TRUE); console_kit_session_emit_lock (cksession); } void ck_session_unlock (CkSession *session) { ConsoleKitSession *cksession; TRACE (); g_return_if_fail (CK_IS_SESSION (session)); cksession = CONSOLE_KIT_SESSION (session); g_debug ("Emitting unlock for session %s", session->priv->id); console_kit_session_set_locked_hint (cksession, FALSE); console_kit_session_emit_unlock (cksession); } static gboolean dbus_lock (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); ck_session_lock (CK_SESSION (cksession)); console_kit_session_complete_lock (cksession, context); return TRUE; } static gboolean dbus_unlock (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); ck_session_unlock (CK_SESSION (cksession)); console_kit_session_complete_unlock (cksession, context); return TRUE; } /* adapted from PolicyKit */ static gboolean get_caller_info (CkSession *session, const char *sender, uid_t *calling_uid, pid_t *calling_pid) { gboolean res = FALSE; GVariant *value = NULL; GError *error = NULL; if (sender == NULL) { goto out; } value = g_dbus_proxy_call_sync (session->priv->bus_proxy, "GetConnectionUnixUser", g_variant_new ("(s)", sender), G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &error); if (value == NULL) { g_warning ("GetConnectionUnixUser() failed: %s", error->message); g_error_free (error); goto out; } g_variant_get (value, "(u)", calling_uid); g_variant_unref (value); value = g_dbus_proxy_call_sync (session->priv->bus_proxy, "GetConnectionUnixProcessID", g_variant_new ("(s)", sender), G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &error); if (value == NULL) { g_warning ("GetConnectionUnixProcessID() failed: %s", error->message); g_error_free (error); goto out; } g_variant_get (value, "(u)", calling_pid); g_variant_unref (value); res = TRUE; g_debug ("uid = %d", *calling_uid); g_debug ("pid = %d", *calling_pid); out: return res; } static gboolean session_set_idle_hint_internal (CkSession *session, gboolean idle_hint) { ConsoleKitSession *cksession = CONSOLE_KIT_SESSION (session); if (console_kit_session_get_idle_hint (cksession) != idle_hint) { console_kit_session_set_idle_hint (cksession, idle_hint); /* FIXME: can we get a time from the dbus message? */ g_get_current_time (&session->priv->idle_since_hint); g_debug ("Emitting idle-changed for session %s", session->priv->id); console_kit_session_emit_idle_hint_changed (cksession, idle_hint); } return TRUE; } static gboolean dbus_get_idle_since_hint (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { CkSession *session = CK_SESSION(cksession); char *date_str; TRACE (); g_return_val_if_fail (CK_IS_SESSION (cksession), FALSE); if (console_kit_session_get_idle_hint (cksession) == FALSE) { throw_error (context, CK_SESSION_ERROR_GENERAL, "idle since hint not set"); return TRUE; } date_str = g_time_val_to_iso8601 (&session->priv->idle_since_hint); console_kit_session_complete_get_idle_since_hint (cksession, context, date_str); g_free (date_str); return TRUE; } static gboolean dbus_get_idle_hint (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); console_kit_session_complete_get_idle_hint (cksession, context, console_kit_session_get_idle_hint (cksession)); return TRUE; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Session1 \ org.freedesktop.ConsoleKit.Session.SetIdleHint boolean:TRUE */ static gboolean dbus_set_idle_hint (ConsoleKitSession *cksession, GDBusMethodInvocation *context, gboolean idle_hint) { const char *sender; uid_t calling_uid = 0; pid_t calling_pid = 0; gboolean res; CkSession *session; TRACE (); g_return_val_if_fail (CK_IS_SESSION (cksession), FALSE); session = CK_SESSION(cksession); sender = g_dbus_method_invocation_get_sender (context); res = get_caller_info (session, sender, &calling_uid, &calling_pid); if (! res) { g_warning ("stat on pid %d failed", calling_pid); throw_error (context, CK_SESSION_ERROR_FAILED, _("Unable to lookup information about calling process '%d'"), calling_pid); return TRUE; } /* only restrict this by UID for now */ if (console_kit_session_get_unix_user (cksession) != calling_uid) { throw_error (context, CK_SESSION_ERROR_INSUFFICIENT_PERMISSION, _("Only session owner may set idle hint state")); return TRUE; } session_set_idle_hint_internal (session, idle_hint); console_kit_session_complete_set_idle_hint (cksession, context); return TRUE; } /* Example: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Session1 \ org.freedesktop.ConsoleKit.Session.SetLockedHint boolean:TRUE */ static gboolean dbus_set_locked_hint (ConsoleKitSession *cksession, GDBusMethodInvocation *context, gboolean arg_locked_hint) { const char *sender; uid_t calling_uid = 0; pid_t calling_pid = 0; gboolean res; CkSession *session; TRACE (); g_return_val_if_fail (CK_IS_SESSION (cksession), FALSE); session = CK_SESSION(cksession); sender = g_dbus_method_invocation_get_sender (context); res = get_caller_info (session, sender, &calling_uid, &calling_pid); if (! res) { g_warning ("stat on pid %d failed", calling_pid); throw_error (context, CK_SESSION_ERROR_FAILED, _("Unable to lookup information about calling process '%d'"), calling_pid); return TRUE; } /* only restrict this by UID for now */ if (console_kit_session_get_unix_user (cksession) != calling_uid) { throw_error (context, CK_SESSION_ERROR_INSUFFICIENT_PERMISSION, _("Only session owner may set locked hint state")); return TRUE; } console_kit_session_set_locked_hint (cksession, arg_locked_hint); console_kit_session_complete_set_idle_hint (cksession, context); return TRUE; } static gboolean dbus_get_session_service (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *session_service = console_kit_session_get_session_service (cksession); TRACE (); if (session_service == NULL) { /* default to unspecified */ session_service = "unspecified"; } console_kit_session_complete_get_session_service (cksession, context, session_service); return TRUE; } static gboolean dbus_get_session_type (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *session_type = console_kit_session_get_session_type (cksession); TRACE (); if (session_type == NULL) { /* default to unspecified */ session_type = "unspecified"; } console_kit_session_complete_get_session_type (cksession, context, session_type); return TRUE; } static gboolean dbus_get_session_class (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *session_class = console_kit_session_get_session_class (cksession); TRACE (); if (session_class == NULL) { /* default to user */ session_class = "user"; } console_kit_session_complete_get_session_class (cksession, context, session_class); return TRUE; } static gboolean dbus_get_session_state (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *state = console_kit_session_get_session_state (cksession); TRACE (); if (state == NULL) { /* default to online, but this shouldn't really happen */ state = "online"; } console_kit_session_complete_get_session_state (cksession, context, state); return TRUE; } static void ck_session_print_list_size (CkSession *session) { #if defined(CONSOLEKIT_DEBUGGING) g_debug ("session %s list size is %d", session->priv->id, g_list_length (session->priv->devices)); #endif } static void ck_session_check_paused_devices (CkSession *session) { ConsoleKitSession *cksession = CONSOLE_KIT_SESSION (session); GList *itr; TRACE (); ck_session_print_list_size (session); /* See if we've paused all the devices in the session */ for (itr = session->priv->devices; itr != NULL; itr = g_list_next (itr)) { CkDevice *device = CK_DEVICE (itr->data); if (ck_device_get_active (device)) { return; } } /* If we didn't force the state change, do it now */ if (console_kit_session_get_active (cksession) != FALSE) { g_debug ("marking session %s inactive", session->priv->id); console_kit_session_set_active (cksession, FALSE); console_kit_session_emit_active_changed (cksession, FALSE); console_kit_session_set_session_state (cksession, "online"); } if (session->priv->pause_devices_timer != 0) { g_source_remove (session->priv->pause_devices_timer); session->priv->pause_devices_timer = 0; } } static gboolean force_pause_devices (CkSession *session) { GList *itr; TRACE (); ck_session_print_list_size (session); for (itr = session->priv->devices; itr != NULL; itr = g_list_next (itr)) { ck_device_set_active (CK_DEVICE (itr->data), FALSE); } session->priv->pause_devices_timer = 0; ck_session_check_paused_devices (session); return FALSE; } static void ck_session_pause_all_devices (CkSession *session, gboolean force) { ConsoleKitSession *cksession = CONSOLE_KIT_SESSION (session); GList *itr; TRACE (); ck_session_print_list_size (session); for (itr = session->priv->devices; itr != NULL; itr = g_list_next (itr)) { CkDevice *device = CK_DEVICE (itr->data); if (ck_device_get_active (device) == FALSE) { g_debug ("device already paused"); continue; } /* Let the session controller know about the change */ g_debug ("emit pause device for %d, %d, type %s", ck_device_get_major (device), ck_device_get_minor (device), force ? "force" : "pause"); console_kit_session_emit_pause_device (CONSOLE_KIT_SESSION (session), ck_device_get_major (device), ck_device_get_minor (device), force ? "force" : "pause"); if (force) { ck_device_set_active (device, FALSE); } } if (force || session->priv->devices == NULL) { g_debug ("marking session %s inactive", session->priv->id); console_kit_session_set_active (cksession, FALSE); console_kit_session_emit_active_changed (cksession, FALSE); console_kit_session_set_session_state (cksession, "online"); } else { session->priv->pause_devices_timer = g_timeout_add_seconds (3, (GSourceFunc)force_pause_devices, session); } } static void ck_session_debug_print_dbus_message (CkSession *session, GDBusMessage *message) { #if defined(CONSOLEKIT_DEBUGGING) gchar *string = g_dbus_message_print (message, 4); gchar **split_string = g_strsplit (string, "\n", 0); gint i; for (i = 0; split_string != NULL && split_string[i] != NULL; i++) { g_debug ("%s", split_string[i]); } g_strfreev (split_string); g_free (string); #endif } static void ck_session_resume_all_devices (CkSession *session) { ConsoleKitSession *cksession = CONSOLE_KIT_SESSION (session); GList *itr; gint vtnr; TRACE (); vtnr = console_kit_session_get_vtnr (cksession); /* Give ownership of the active console device to the user */ if (vtnr > 0) { struct passwd *pwent; gint fd; gint uid; uid = console_kit_session_get_unix_user (cksession); fd = ck_open_a_console (ck_get_console_device_for_num (vtnr)); if (fd >= 0) { errno = 0; pwent = getpwuid (uid); if (pwent == NULL) { g_warning ("Unable to lookup UID: %s", g_strerror (errno)); errno = 0; } else { if (fchown (fd, uid, pwent->pw_gid) != 0) { g_warning ("Failed to chown console device, reason was: %s", strerror(errno)); errno = 0; } } g_close (fd, NULL); } } /* without a controller, we just mark ourselved active */ if (session->priv->session_controller == NULL) { g_debug ("no session controller: marking session active"); console_kit_session_set_active (cksession, TRUE); console_kit_session_emit_active_changed (cksession, TRUE); console_kit_session_set_session_state (cksession, "active"); return; } ck_session_print_list_size (session); for (itr = session->priv->devices; itr != NULL; itr = g_list_next (itr)) { CkDevice *device = CK_DEVICE (itr->data); GVariant *body; GDBusMessage *message; GUnixFDList *out_fd_list = NULL; gint fd = -1; gint fd2 = -1; ck_device_set_active (device, TRUE); fd = ck_device_get_fd (device); if (fd < 0) { g_debug ("Unable to signal ResumeDevice, failed to get device"); continue; } message = g_dbus_message_new_signal (session->priv->id, CK_SESSION_DBUS_NAME, "ResumeDevice"); /* We always send to the session controller */ g_dbus_message_set_destination (message, session->priv->session_controller); body = g_variant_new ("(uu@h)", ck_device_get_major (device), ck_device_get_minor (device), g_variant_new_handle (0)); g_dbus_message_set_body (message, body); /* we need to copy this, because gdbus closes the fd on us */ fd2 = dup (fd); out_fd_list = g_unix_fd_list_new_from_array (&fd2, 1); g_dbus_message_set_unix_fd_list (message, out_fd_list); g_debug ("sending ResumeDevice signal to session controller"); ck_session_debug_print_dbus_message (session, message); /* Let only the session controller know about the change and * give them the new fd. */ g_dbus_connection_send_message (session->priv->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_clear_object (&out_fd_list); g_clear_object (&message); } g_debug ("marking session active"); console_kit_session_set_active (cksession, TRUE); console_kit_session_emit_active_changed (cksession, TRUE); console_kit_session_set_session_state (cksession, "active"); } gboolean ck_session_set_active (CkSession *session, gboolean active, gboolean force) { ConsoleKitSession *cksession; TRACE (); g_return_val_if_fail (CK_IS_SESSION (session), FALSE); cksession = CONSOLE_KIT_SESSION (session); if (console_kit_session_get_active (cksession) == active) { /* redundant call, we shouldn't need to do anything */ return TRUE; } if (session->priv->pause_devices_timer != 0) { g_source_remove (session->priv->pause_devices_timer); session->priv->pause_devices_timer = 0; } g_debug ("ck_session_set_active: session %s changing to %s, forced? %s", session->priv->id, active ? "active" : "not active", force ? "yes" : "no"); /* We handle device events then change the active state */ if (active == FALSE) { ck_session_pause_all_devices (session, force); } else { ck_session_resume_all_devices (session); } return TRUE; } static gboolean dbus_is_active (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); console_kit_session_complete_is_active (cksession, context, console_kit_session_get_active (cksession)); return TRUE; } static gboolean dbus_activate (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { GError *error = NULL; GError *initial_error; CkSession *session = CK_SESSION (cksession); TRACE (); g_return_val_if_fail (session, FALSE); /* Set an initial error message in the event the signal isn't handeled */ g_set_error (&error, CK_SESSION_ERROR, CK_SESSION_ERROR_NOT_SUPPORTED, _("Activate signal not handeled. Session not attached to seat, or the seat doesn't support activation changes")); /* keep track of the starting error because the call to g_signal_emit * may change it and we still need to free it */ initial_error = error; g_signal_emit (session, signals [ACTIVATE], 0, context, &error); if (error != NULL) { /* if the signal is not handled then either: a) aren't attached to seat b) seat doesn't support activation changes */ g_debug ("Got error message: %s", error->message); /* translate and throw the error */ switch (error->code) { case CK_SEAT_ERROR_ALREADY_ACTIVE: /* Don't care */ break; case CK_SEAT_ERROR_NOT_SUPPORTED: throw_error (context, CK_SESSION_ERROR_NOT_SUPPORTED, error->message); break; default: throw_error (context, CK_SESSION_ERROR_GENERAL, error->message); } g_clear_error (&error); g_clear_error (&initial_error); return TRUE; } g_clear_error (&initial_error); console_kit_session_complete_activate (cksession, context); return TRUE; } static gboolean dbus_get_id (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { CkSession *session = CK_SESSION (cksession); gchar *id; TRACE (); g_return_val_if_fail (CK_IS_SESSION (session), FALSE); id = session->priv->id; if (id == NULL) { id = ""; } console_kit_session_complete_get_id (cksession, context, session->priv->id); return TRUE; } gboolean ck_session_get_id (CkSession *session, char **id, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); if (id != NULL) { *id = g_strdup (session->priv->id); } return TRUE; } static gboolean dbus_get_seat_id (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { CkSession *session = CK_SESSION (cksession); const gchar *seat_id; TRACE (); g_return_val_if_fail (CK_IS_SESSION (session), FALSE); seat_id = session->priv->seat_id; if (seat_id == NULL) { throw_error (context, CK_SESSION_ERROR_FAILED, "session not attached to a seat"); return TRUE; } console_kit_session_complete_get_seat_id (cksession, context, session->priv->seat_id); return TRUE; } gboolean ck_session_get_seat_id (CkSession *session, char **id, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); if (id != NULL) { *id = g_strdup (session->priv->seat_id); } return TRUE; } static gboolean dbus_get_user (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); console_kit_session_complete_get_unix_user (cksession, context, console_kit_session_get_unix_user (cksession)); return TRUE; } static gboolean dbus_get_unix_user (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); console_kit_session_complete_get_unix_user (cksession, context, console_kit_session_get_unix_user (cksession)); return TRUE; } gboolean ck_session_set_unix_user (CkSession *session, guint uid, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); console_kit_session_set_unix_user (CONSOLE_KIT_SESSION (session), uid); return TRUE; } static gboolean dbus_get_x11_display (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *x11_display; TRACE (); x11_display = console_kit_session_get_x11_display (cksession); if (x11_display == NULL) { x11_display = ""; } console_kit_session_complete_get_x11_display (cksession, context, x11_display); return TRUE; } gboolean ck_session_set_x11_display (CkSession *session, const char *x11_display, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); console_kit_session_set_x11_display (CONSOLE_KIT_SESSION (session), x11_display); return TRUE; } static gboolean dbus_get_display_device (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *display_device; TRACE (); display_device = console_kit_session_get_display_device (cksession); if (display_device == NULL) { display_device = ""; } console_kit_session_complete_get_x11_display_device (cksession, context, display_device); return TRUE; } gboolean ck_session_set_display_device (CkSession *session, const char *display_device, GError **error) { ConsoleKitSession *cksession; g_return_val_if_fail (CK_IS_SESSION (session), FALSE); cksession = CONSOLE_KIT_SESSION (session); console_kit_session_set_display_device (cksession, display_device); return TRUE; } static gboolean dbus_get_x11_display_device (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *x11_display_device; TRACE (); x11_display_device = console_kit_session_get_x11_display_device (cksession); if (x11_display_device == NULL) { x11_display_device = ""; } console_kit_session_complete_get_x11_display_device (cksession, context, x11_display_device); return TRUE; } gboolean ck_session_set_x11_display_device (CkSession *session, const char *x11_display_device, GError **error) { ConsoleKitSession *cksession; g_return_val_if_fail (CK_IS_SESSION (session), FALSE); cksession = CONSOLE_KIT_SESSION (session); console_kit_session_set_x11_display_device (cksession, x11_display_device); return TRUE; } static gboolean dbus_get_remote_host_name (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { const gchar *remote_host_name = console_kit_session_get_remote_host_name (cksession); TRACE (); if (remote_host_name == NULL) { remote_host_name = ""; } console_kit_session_complete_get_remote_host_name (cksession, context, remote_host_name); return TRUE; } gboolean ck_session_set_remote_host_name (CkSession *session, const char *remote_host_name, GError **error) { ConsoleKitSession *cksession; g_return_val_if_fail (CK_IS_SESSION (session), FALSE); cksession = CONSOLE_KIT_SESSION (session); console_kit_session_set_remote_host_name (cksession, remote_host_name); return TRUE; } static gboolean dbus_get_creation_time (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { CkSession *session = CK_SESSION(cksession); TRACE (); g_return_val_if_fail (CK_IS_SESSION (cksession), FALSE); console_kit_session_complete_get_creation_time (cksession, context, g_time_val_to_iso8601 (&session->priv->creation_time)); return TRUE; } gboolean ck_session_get_creation_time (CkSession *session, char **iso8601_datetime, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); if (iso8601_datetime != NULL) { *iso8601_datetime = g_time_val_to_iso8601 (&session->priv->creation_time); } return TRUE; } static gboolean dbus_is_local (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); console_kit_session_complete_is_local (cksession, context, console_kit_session_get_is_local (cksession)); return TRUE; } gboolean ck_session_set_is_local (CkSession *session, gboolean is_local, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); console_kit_session_set_is_local (CONSOLE_KIT_SESSION (session), is_local); return TRUE; } gboolean ck_session_is_local (CkSession *session, gboolean *local, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); if (local != NULL) { *local = console_kit_session_get_is_local (CONSOLE_KIT_SESSION (session)); } return TRUE; } gboolean ck_session_set_id (CkSession *session, const char *id, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); g_free (session->priv->id); session->priv->id = g_strdup (id); return TRUE; } gboolean ck_session_set_cookie (CkSession *session, const char *cookie, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); g_free (session->priv->cookie); session->priv->cookie = g_strdup (cookie); return TRUE; } gboolean ck_session_set_seat_id (CkSession *session, const char *id, GError **error) { GVariant *seat = NULL; gchar **seat_split; g_return_val_if_fail (CK_IS_SESSION (session), FALSE); g_free (session->priv->seat_id); session->priv->seat_id = g_strdup (id); if (id != NULL) { /* we need to remove the prefix from the first seat_id returned */ seat_split = g_strsplit (id, "/org/freedesktop/ConsoleKit/", 2); if (seat_split[0] == NULL) { g_critical ("id %s is invalid or g_strsplit has changed", id); return FALSE; } seat = g_variant_new ("(so)", seat_split[1], id); g_strfreev (seat_split); } console_kit_session_set_seat (CONSOLE_KIT_SESSION (session), seat); return TRUE; } /** * ck_session_set_runtime_dir * @session: CkSession object * @runtime_dir: The XDG_RUNTIME_DIR for the user of this session. For details, see: * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html * returns: TRUE if successfully set, FALSE on failure. **/ gboolean ck_session_set_runtime_dir (CkSession *session, const char *runtime_dir) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); g_free (session->priv->runtime_dir); session->priv->runtime_dir = g_strdup (runtime_dir); return TRUE; } /** * ck_session_get_runtime_dir * @session: CkSession object * returns: The XDG_RUNTIME_DIR. For details, see: * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html **/ const char * ck_session_get_runtime_dir (CkSession *session) { g_return_val_if_fail (CK_IS_SESSION (session), NULL); return session->priv->runtime_dir; } static gboolean dbus_get_runtime_dir (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { CkSession *session = CK_SESSION(cksession); TRACE (); g_return_val_if_fail (CK_IS_SESSION (cksession), FALSE); /* if no login session id is set return an empty string */ if (session->priv->runtime_dir == NULL) { throw_error (context, CK_SESSION_ERROR_FAILED, _("Failed to create the XDG_RUNTIME_DIR")); return TRUE; } console_kit_session_complete_get_xdgruntime_dir (cksession, context, session->priv->runtime_dir); return TRUE; } static gboolean dbus_get_login_session_id (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { CkSession *session = CK_SESSION(cksession); const gchar *login_session_id; TRACE (); g_return_val_if_fail (CK_IS_SESSION (cksession), FALSE); login_session_id = session->priv->login_session_id; /* if no login session id is set return an empty string */ if (login_session_id == NULL) { login_session_id = ""; } console_kit_session_complete_get_login_session_id (cksession, context, login_session_id); return TRUE; } static gboolean dbus_get_vtnr (ConsoleKitSession *cksession, GDBusMethodInvocation *context) { TRACE (); console_kit_session_complete_get_vtnr (cksession, context, console_kit_session_get_vtnr (cksession)); return TRUE; } gboolean ck_session_set_login_session_id (CkSession *session, const char *login_session_id, GError **error) { g_return_val_if_fail (CK_IS_SESSION (session), FALSE); g_free (session->priv->login_session_id); session->priv->login_session_id = g_strdup (login_session_id); return TRUE; } gboolean ck_session_set_session_service (CkSession *session, const char *service, GError **error) { ConsoleKitSession *cksession = CONSOLE_KIT_SESSION (session); g_return_val_if_fail (CK_IS_SESSION (session), FALSE); console_kit_session_set_session_service (cksession, service); return TRUE; } gboolean ck_session_set_session_type (CkSession *session, const char *type, GError **error) { ConsoleKitSession *cksession = CONSOLE_KIT_SESSION (session); g_return_val_if_fail (CK_IS_SESSION (session), FALSE); console_kit_session_set_session_type (cksession, type); return TRUE; } static gboolean vt_leave_handler (gpointer data) { CkSession *session = CK_SESSION (data); TRACE (); /* g_unix_signal_add_full returns this callback in the GMainContext * so we don't have the limitations of POSIX signal handlers */ /* Forcably disable all devices, we have to do this * now or we'll crash Xorg if it's running as root on * the new VT */ ck_session_pause_all_devices (session, TRUE); /* release control */ #if defined(VT_RELDISP) ioctl (session->priv->tty_fd, VT_RELDISP, 1); #endif return TRUE; } static gboolean vt_acquire_handler (gpointer data) { CkSession *session = CK_SESSION (data); TRACE (); /* g_unix_signal_add_full returns this callback in the GMainContext * so we don't have the limitations of POSIX signal handlers */ /* ack that we are getting control, but let the normal * process handle granting access */ #if defined(VT_RELDISP) ioctl (session->priv->tty_fd, VT_RELDISP, VT_ACKACQ); #endif return TRUE; } static void ck_session_setup_vt_signal (CkSession *session, guint vtnr) { #if defined(KDGKBMODE) && defined(KDSETMODE) && defined(KD_GRAPHICS) struct vt_mode mode = { 0 }; int graphical_mode = KD_TEXT; session->priv->tty_fd = ck_open_a_console (ck_get_console_device_for_num (vtnr)); if (session->priv->tty_fd < 0) { return; } ioctl(session->priv->tty_fd, KDGKBMODE, &session->priv->old_kbd_mode); /* So during setup here, we need to ensure we're in graphical mode, * otherwise it will try to draw stuff in the background */ #if defined(KDGETMODE) if (ioctl (session->priv->tty_fd, KDGETMODE, &graphical_mode) != 0) { g_warning ("failed to get current VT mode"); return; } #endif if (graphical_mode == KD_TEXT) { if (ioctl (session->priv->tty_fd, KDSETMODE, KD_GRAPHICS) != 0) { g_warning ("failed to change VT to graphical mode"); return; } } else { g_debug ("already running in graphical mode? not messing with the tty or VT"); return; } /* We define KDSKBMUTE above so we can't do the usual check */ #if defined(__linux__) if (ioctl (session->priv->tty_fd, KDSKBMUTE, 1) != 0) { g_warning ("failed to mute FD with KDSKBMUTE"); } #endif /* defined(__linux__) */ #if defined(KDSKBMODE) if (ioctl (session->priv->tty_fd, KDSKBMODE, KBD_OFF_MODE) != 0) { g_warning ("failed to turn off keyboard"); } #endif mode.mode = VT_PROCESS; mode.relsig = SIGUSR1; mode.acqsig = SIGUSR2; mode.frsig = SIGIO; /* not used, but has to be set anyway */ if (ioctl (session->priv->tty_fd, VT_SETMODE, &mode) < 0) { g_warning ("failed to take control of vt handling"); return; } session->priv->sig_watch_s1 = g_unix_signal_add_full (G_PRIORITY_HIGH, SIGUSR1, (GSourceFunc)vt_leave_handler, session, NULL); session->priv->sig_watch_s2 = g_unix_signal_add_full (G_PRIORITY_HIGH, SIGUSR2, (GSourceFunc)vt_acquire_handler, session, NULL); #endif /* defined(KDGKBMODE) && defined(KDSETMODE) && defined(KD_GRAPHICS) */ } static void session_controller_vanished (GDBusConnection *connection, const gchar *name, gpointer user_data) { CkSession *session = CK_SESSION (user_data); TRACE (); session->priv->session_controller_watchid = 0; ck_session_set_session_controller (session, NULL); } static void ck_session_controller_cleanup (CkSession *session) { TRACE (); if (session->priv->session_controller_watchid != 0) { g_bus_unwatch_name (session->priv->session_controller_watchid); session->priv->session_controller_watchid = 0; } if (session->priv->pause_devices_timer != 0) { g_source_remove (session->priv->pause_devices_timer); session->priv->pause_devices_timer = 0; } if (session->priv->session_controller) { g_free (session->priv->session_controller); session->priv->session_controller = NULL; } ck_session_remove_all_devices (session); #if defined(VT_SETMODE) /* Remove the old signal call backs, restore VT switching to auto * and text mode (put it back the way we found it) */ if (session->priv->sig_watch_s1 != 0) { struct vt_mode mode = { 0 }; mode.mode = VT_AUTO; /* We define KDSKBMUTE above so we can't do the usual check */ #if defined(__linux__) if (ioctl (session->priv->tty_fd, KDSKBMUTE, 0) != 0) { g_warning ("failed to unmute FD with KDSKBMUTE"); } #endif /* defined(__linux__) */ #if defined(KDSKBMODE) if (ioctl(session->priv->tty_fd, KDSKBMODE, session->priv->old_kbd_mode) != 0) { g_warning ("failed to restore old keyboard mode"); } #endif /* defined(KDSKBMODE) */ if (ioctl (session->priv->tty_fd, VT_SETMODE, &mode) < 0) { g_warning ("failed to return control of vt handling"); } if (ioctl (session->priv->tty_fd, KDSETMODE, KD_TEXT) < 0) { g_warning ("failed to return to text mode for the VT"); } g_source_remove (session->priv->sig_watch_s1); session->priv->sig_watch_s1 = 0; g_source_remove (session->priv->sig_watch_s2); session->priv->sig_watch_s2 = 0; } /* Close the old tty fd */ if (session->priv->tty_fd != -1) { g_close (session->priv->tty_fd, NULL); session->priv->tty_fd = -1; } #endif /* defined(VT_SETMODE) */ } void ck_session_set_session_controller (CkSession *session, const gchar *bus_name) { guint vtnr; TRACE (); /* clean up after the old controller */ ck_session_controller_cleanup (session); /* There's no reason to go further if we're removing the session * controller */ if (bus_name == NULL) { return; } session->priv->session_controller = g_strdup (bus_name); /* if the session controller crashes or exits, we need to drop access * to all the devices it requested and let someone else become the * session controller. */ session->priv->session_controller_watchid = g_bus_watch_name_on_connection (session->priv->connection, bus_name, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, session_controller_vanished, session, NULL); vtnr = console_kit_session_get_vtnr (CONSOLE_KIT_SESSION (session)); if (vtnr > 0) { ck_session_setup_vt_signal (session, vtnr); } } static gboolean dbus_can_control_session (ConsoleKitSession *object, GDBusMethodInvocation *invocation) { console_kit_session_complete_can_control_session (object, invocation, ck_device_is_server_managed ()); return TRUE; } static gboolean dbus_take_control (ConsoleKitSession *object, GDBusMethodInvocation *invocation, gboolean arg_force) { CkSession *session = CK_SESSION (object); uid_t uid = 0; pid_t pid = 0; const gchar *sender = g_dbus_method_invocation_get_sender (invocation); TRACE (); if (!ck_device_is_server_managed ()) { throw_error (invocation, CK_SESSION_ERROR_NOT_SUPPORTED, _("Server managed devices not supported")); return TRUE; } if (!get_caller_info (session, sender, &uid, &pid)) { throw_error (invocation, CK_SESSION_ERROR_GENERAL, _("Failed to get uid of dbus caller")); return TRUE; } if (g_strcmp0 (session->priv->session_controller, sender) == 0) { /* The current session controller is trying to take control * again? Odd, but we'll just do nothing here. */ } else if (session->priv->session_controller == NULL || (arg_force == TRUE && uid == 0)) { ck_session_set_session_controller (CK_SESSION (session), sender); } else { if (arg_force == TRUE) { throw_error (invocation, CK_SESSION_ERROR_INSUFFICIENT_PERMISSION, _("Failed to replace the current session controller")); } else { throw_error (invocation, CK_SESSION_ERROR_FAILED, _("Session controller already present")); } return TRUE; } console_kit_session_complete_take_control (object, invocation); return TRUE; } static gboolean dbus_release_control (ConsoleKitSession *object, GDBusMethodInvocation *invocation) { CkSession *session = CK_SESSION (object); const gchar *sender = g_dbus_method_invocation_get_sender (invocation); TRACE (); /* only the session controller can release it */ if (g_strcmp0 (session->priv->session_controller, sender) == 0) { ck_session_set_session_controller (CK_SESSION (object), NULL); } else { throw_error (invocation, CK_SESSION_ERROR_FAILED, _("Only the session controller may use this function")); return TRUE; } console_kit_session_complete_release_control (object, invocation); return TRUE; } static CkDevice* ck_session_get_device (CkSession *session, guint major, guint minor) { GList *iter; TRACE (); ck_session_print_list_size (session); for (iter = session->priv->devices; iter != NULL; iter = g_list_next (iter)) { if (ck_device_compare (iter->data, major, minor)) { g_debug ("found device"); return iter->data; } } g_debug ("failed to find deivce"); return NULL; } static CkDevice* ck_session_create_device (CkSession *session, guint major, guint minor) { CkDevice *device = ck_session_get_device (session, major, minor); /* If the device already exists for this session don't * create it again */ if (device == NULL) { g_debug ("creating new device"); device = ck_device_new (major, minor, console_kit_session_get_active (CONSOLE_KIT_SESSION (session))); if (device != NULL && CK_IS_DEVICE (device)) { g_debug ("adding device to the list"); session->priv->devices = g_list_prepend (session->priv->devices, device); ck_session_print_list_size (session); } } return device; } static void ck_session_remove_device (CkSession *session, CkDevice *device) { TRACE (); ck_session_print_list_size (session); session->priv->devices = g_list_remove (session->priv->devices, device); ck_session_print_list_size (session); } static void ck_session_remove_all_devices (CkSession *session) { TRACE (); ck_session_print_list_size (session); g_list_free_full (session->priv->devices, g_object_unref); session->priv->devices = NULL; g_debug ("list size is now 0"); } static gboolean dbus_take_device (ConsoleKitSession *object, GDBusMethodInvocation *invocation, GUnixFDList *fd_list, guint arg_major, guint arg_minor) { CkSession *session = CK_SESSION (object); CkDevice *device; const gchar *sender = g_dbus_method_invocation_get_sender (invocation); gint fd = -1; GUnixFDList *out_fd_list = NULL; TRACE (); /* only the session controller can call us */ if (g_strcmp0 (session->priv->session_controller, sender) != 0) { throw_error (invocation, CK_SESSION_ERROR_FAILED, _("Only the session controller may call this function")); return TRUE; } /* you can't request the device again, that's confusing */ if (ck_session_get_device (session, arg_major, arg_minor)) { throw_error (invocation, CK_SESSION_ERROR_GENERAL, _("Device has already been requested")); return TRUE; } device = ck_session_create_device (session, arg_major, arg_minor); if (device == NULL) { throw_error (invocation, CK_SESSION_ERROR_NOT_SUPPORTED, _("Failed to create device")); return TRUE; } fd = ck_device_get_fd (device); if (fd == -1) { throw_error (invocation, CK_SESSION_ERROR_NOT_SUPPORTED, _("Failed to get file descriptor for device")); return TRUE; } out_fd_list = g_unix_fd_list_new_from_array (&fd, 1); console_kit_session_complete_take_device (object, invocation, out_fd_list, g_variant_new_handle (0), console_kit_session_get_active (object)); return TRUE; } static gboolean dbus_release_device (ConsoleKitSession *object, GDBusMethodInvocation *invocation, guint arg_major, guint arg_minor) { CkSession *session = CK_SESSION (object); CkDevice *device; const gchar *sender = g_dbus_method_invocation_get_sender (invocation); TRACE (); /* only the session controller can call us */ if (g_strcmp0 (session->priv->session_controller, sender) != 0) { throw_error (invocation, CK_SESSION_ERROR_FAILED, _("Only the session controller may call this function")); return TRUE; } device = ck_session_get_device (session, arg_major, arg_minor); if (device == NULL) { throw_error (invocation, CK_SESSION_ERROR_FAILED, _("Device doesn't exist")); return TRUE; } ck_session_remove_device (session, device); g_object_unref (device); console_kit_session_complete_release_device (object, invocation); return TRUE; } static gboolean dbus_pause_device_complete (ConsoleKitSession *object, GDBusMethodInvocation *invocation, guint arg_major, guint arg_minor) { CkSession *session = CK_SESSION (object); CkDevice *device; const gchar *sender = g_dbus_method_invocation_get_sender (invocation); TRACE (); /* only the session controller can call us */ if (g_strcmp0 (session->priv->session_controller, sender) != 0) { throw_error (invocation, CK_SESSION_ERROR_FAILED, _("Only the session controller may call this function")); return TRUE; } device = ck_session_get_device (session, arg_major, arg_minor); if (device == NULL) { throw_error (invocation, CK_SESSION_ERROR_FAILED, _("Device doesn't exist")); return TRUE; } ck_device_set_active (device, FALSE); ck_session_check_paused_devices (session); console_kit_session_complete_pause_device_complete (object, invocation); return TRUE; } static void ck_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { CkSession *self; self = CK_SESSION (object); switch (prop_id) { case PROP_ID: ck_session_set_id (self, g_value_get_string (value), NULL); break; case PROP_COOKIE: ck_session_set_cookie (self, g_value_get_string (value), NULL); break; case PROP_LOGIN_SESSION_ID: ck_session_set_login_session_id (self, g_value_get_string (value), NULL); break; case PROP_SESSION_CONTROLLER: ck_session_set_session_controller (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ck_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { CkSession *self; self = CK_SESSION (object); switch (prop_id) { case PROP_ID: g_value_set_string (value, self->priv->id); break; case PROP_COOKIE: g_value_set_string (value, self->priv->cookie); break; case PROP_LOGIN_SESSION_ID: g_value_set_string (value, self->priv->login_session_id); break; case PROP_SESSION_CONTROLLER: g_value_set_string (value, self->priv->session_controller); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } #define IS_STR_SET(x) (x != NULL && x[0] != '\0') static gboolean session_is_text (CkSession *session) { ConsoleKitSession *cksession; gboolean ret; ret = FALSE; cksession = CONSOLE_KIT_SESSION (session); if (! IS_STR_SET (console_kit_session_get_x11_display_device (cksession)) && ! IS_STR_SET (console_kit_session_get_x11_display (cksession)) && IS_STR_SET (console_kit_session_get_display_device (cksession))) { ret = TRUE; } g_debug ("Identified session '%s' as %s", session->priv->id, ret ? "text" : "graphical"); return ret; } static void tty_idle_changed_cb (CkTtyIdleMonitor *monitor, gboolean idle_hint, CkSession *session) { session_set_idle_hint_internal (session, idle_hint); } static void session_add_activity_watch (CkSession *session) { if (session->priv->idle_monitor == NULL) { session->priv->idle_monitor = ck_tty_idle_monitor_new (console_kit_session_get_display_device (CONSOLE_KIT_SESSION (session))); g_signal_connect (session->priv->idle_monitor, "idle-hint-changed", G_CALLBACK (tty_idle_changed_cb), session); } ck_tty_idle_monitor_start (session->priv->idle_monitor); } static void session_remove_activity_watch (CkSession *session) { TRACE (); if (session->priv->idle_monitor == NULL) { return; } ck_tty_idle_monitor_stop (session->priv->idle_monitor); g_object_unref (session->priv->idle_monitor); session->priv->idle_monitor = NULL; } static GObject * ck_session_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { CkSession *session; session = CK_SESSION (G_OBJECT_CLASS (ck_session_parent_class)->constructor (type, n_construct_properties, construct_properties)); if (session_is_text (session)) { session_add_activity_watch (session); } return G_OBJECT (session); } static void ck_session_class_init (CkSessionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructor = ck_session_constructor; object_class->get_property = ck_session_get_property; object_class->set_property = ck_session_set_property; object_class->finalize = ck_session_finalize; signals [ACTIVATE] = g_signal_new ("activate", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkSessionClass, activate), NULL, NULL, ck_marshal_POINTER__POINTER, G_TYPE_POINTER, 1, G_TYPE_POINTER); /* Install private properties we're not exporting over D-BUS */ g_object_class_install_property (object_class, PROP_ID, g_param_spec_string ("id", "id", "id", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_COOKIE, g_param_spec_string ("cookie", "cookie", "cookie", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_LOGIN_SESSION_ID, g_param_spec_string ("login-session-id", "login-session-id", "login session id", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_SESSION_CONTROLLER, g_param_spec_string ("session-controller", "session-controller", "session-controller", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_type_class_add_private (klass, sizeof (CkSessionPrivate)); } static void ck_session_init (CkSession *session) { session->priv = CK_SESSION_GET_PRIVATE (session); /* FIXME: should we have a property for this? */ g_get_current_time (&session->priv->creation_time); session->priv->tty_fd = -1; } static void ck_session_iface_init (ConsoleKitSessionIface *iface) { iface->handle_activate = dbus_activate; iface->handle_set_idle_hint = dbus_set_idle_hint; iface->handle_set_locked_hint = dbus_set_locked_hint; iface->handle_get_unix_user = dbus_get_unix_user; iface->handle_get_seat_id = dbus_get_seat_id; iface->handle_get_login_session_id = dbus_get_login_session_id; iface->handle_get_vtnr = dbus_get_vtnr; iface->handle_get_session_service = dbus_get_session_service; iface->handle_get_session_type = dbus_get_session_type; iface->handle_get_session_class = dbus_get_session_class; iface->handle_get_session_state = dbus_get_session_state; iface->handle_get_x11_display_device = dbus_get_x11_display_device; iface->handle_get_display_device = dbus_get_display_device; iface->handle_get_x11_display = dbus_get_x11_display; iface->handle_is_active = dbus_is_active; iface->handle_get_creation_time = dbus_get_creation_time; iface->handle_get_remote_host_name = dbus_get_remote_host_name; iface->handle_get_idle_since_hint = dbus_get_idle_since_hint; iface->handle_is_local = dbus_is_local; iface->handle_get_id = dbus_get_id; iface->handle_get_user = dbus_get_user; iface->handle_lock = dbus_lock; iface->handle_unlock = dbus_unlock; iface->handle_get_idle_hint = dbus_get_idle_hint; iface->handle_get_xdgruntime_dir = dbus_get_runtime_dir; iface->handle_can_control_session = dbus_can_control_session; iface->handle_take_control = dbus_take_control; iface->handle_release_control = dbus_release_control; iface->handle_take_device = dbus_take_device; iface->handle_release_device = dbus_release_device; iface->handle_pause_device_complete = dbus_pause_device_complete; } static void ck_session_finalize (GObject *object) { CkSession *session; g_debug ("ck_session_finalize"); g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_SESSION (object)); session = CK_SESSION (object); g_return_if_fail (session->priv != NULL); session_remove_activity_watch (session); ck_session_set_session_controller (session, NULL); ck_session_remove_all_devices (session); g_free (session->priv->id); g_free (session->priv->cookie); g_free (session->priv->login_session_id); g_free (session->priv->runtime_dir); g_free (session->priv->seat_id); g_free (session->priv->session_controller); if (session->priv->bus_proxy) { g_object_unref(session->priv->bus_proxy); } if (session->priv->session_controller_watchid != 0) { g_bus_unwatch_name (session->priv->session_controller_watchid); } if (session->priv->pause_devices_timer != 0) { g_source_remove (session->priv->pause_devices_timer); session->priv->pause_devices_timer = 0; } G_OBJECT_CLASS (ck_session_parent_class)->finalize (object); } CkSession * ck_session_new (const char *ssid, const char *cookie, GDBusConnection *connection) { GObject *object; gboolean res; object = g_object_new (CK_TYPE_SESSION, "id", ssid, "cookie", cookie, NULL); res = register_session (CK_SESSION (object), connection); if (! res) { g_object_unref (object); return NULL; } return CK_SESSION (object); } CkSession * ck_session_new_with_parameters (const char *ssid, const char *cookie, const GVariant *parameters, GDBusConnection *connection) { GObject *object; gboolean session_registered; GParameter *params; guint n_allocated_params; guint n_params; GObjectClass *class; GType object_type; GVariantIter *iter; gchar *prop_name; GVariant *value; object_type = CK_TYPE_SESSION; class = g_type_class_ref (object_type); g_variant_get ((GVariant *)parameters, "a{sv}", &iter); n_allocated_params = 2; if (parameters != NULL) { n_allocated_params += g_variant_iter_n_children (iter); } params = g_new0 (GParameter, n_allocated_params); n_params = 0; params[n_params].name = g_strdup ("id"); params[n_params].value.g_type = 0; g_value_init (¶ms[n_params].value, G_TYPE_STRING); g_value_set_string (¶ms[n_params].value, ssid); n_params++; params[n_params].name = g_strdup ("cookie"); params[n_params].value.g_type = 0; g_value_init (¶ms[n_params].value, G_TYPE_STRING); g_value_set_string (¶ms[n_params].value, cookie); n_params++; if (parameters != NULL) { while (g_variant_iter_next (iter, "{sv}", &prop_name, &value)) { gboolean res; GValue val_struct = { 0, }; GParamSpec *pspec; if (prop_name == NULL) { g_debug ("Skipping NULL parameter"); goto cleanup; } g_debug ("prop_name = '%s'", prop_name); if (strcmp (prop_name, "id") == 0 || strcmp (prop_name, "cookie") == 0) { g_debug ("Skipping restricted parameter: %s", prop_name); goto cleanup; } pspec = g_object_class_find_property (class, prop_name); if (! pspec) { g_debug ("Skipping unknown parameter: %s", prop_name); goto cleanup; } if (!(pspec->flags & G_PARAM_WRITABLE)) { g_debug ("property '%s' is not writable", pspec->name); goto cleanup; } params[n_params].name = g_strdup (prop_name); params[n_params].value.g_type = 0; g_value_init (¶ms[n_params].value, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_dbus_gvariant_to_gvalue (value, &val_struct); res = g_value_transform (&val_struct, ¶ms[n_params].value); if (! res) { g_debug ("unable to transform property value for '%s'", pspec->name); goto cleanup; } n_params++; cleanup: g_free(prop_name); if (value) { g_variant_unref(value); } } g_variant_iter_free (iter); } object = g_object_newv (object_type, n_params, params); while (n_params--) { g_free ((char *)params[n_params].name); g_value_unset (¶ms[n_params].value); } g_free (params); g_type_class_unref (class); session_registered = register_session (CK_SESSION (object), connection); if (! session_registered) { g_object_unref (object); return NULL; } return CK_SESSION (object); } void ck_session_run_programs (CkSession *session, const char *action) { ConsoleKitSession *cksession; guint n; char *extra_env[11]; /* be sure to adjust this as needed */ TRACE (); n = 0; cksession = CONSOLE_KIT_SESSION (session); extra_env[n++] = g_strdup_printf ("CK_SESSION_ID=%s", session->priv->id); if (console_kit_session_get_session_service (cksession) != NULL) { extra_env[n++] = g_strdup_printf ("CK_SESSION_SERVICE=%s", console_kit_session_get_session_service (cksession)); } if (console_kit_session_get_session_type (cksession) != NULL) { extra_env[n++] = g_strdup_printf ("CK_SESSION_TYPE=%s", console_kit_session_get_session_type (cksession)); } extra_env[n++] = g_strdup_printf ("CK_SESSION_SEAT_ID=%s", session->priv->seat_id); extra_env[n++] = g_strdup_printf ("CK_SESSION_USER_UID=%d", console_kit_session_get_unix_user (cksession)); if (console_kit_session_get_display_device (cksession) != NULL && strlen (console_kit_session_get_display_device (cksession)) > 0) { extra_env[n++] = g_strdup_printf ("CK_SESSION_DISPLAY_DEVICE=%s", console_kit_session_get_display_device (cksession)); } if (console_kit_session_get_x11_display_device (cksession) != NULL && strlen (console_kit_session_get_x11_display_device (cksession) ) > 0) { extra_env[n++] = g_strdup_printf ("CK_SESSION_X11_DISPLAY_DEVICE=%s", console_kit_session_get_x11_display_device (cksession) ); } extra_env[n++] = g_strdup_printf ("CK_SESSION_X11_DISPLAY=%s", console_kit_session_get_x11_display (cksession) ? console_kit_session_get_x11_display (cksession) : ""); if (console_kit_session_get_remote_host_name (cksession) != NULL && strlen (console_kit_session_get_remote_host_name (cksession)) > 0) { extra_env[n++] = g_strdup_printf ("CK_SESSION_REMOTE_HOST_NAME=%s", console_kit_session_get_remote_host_name (cksession)); } extra_env[n++] = g_strdup_printf ("CK_SESSION_IS_ACTIVE=%s", console_kit_session_get_active (cksession) ? "true" : "false"); extra_env[n++] = g_strdup_printf ("CK_SESSION_IS_LOCAL=%s", console_kit_session_get_is_local (cksession) ? "true" : "false"); extra_env[n++] = NULL; g_assert(n <= G_N_ELEMENTS(extra_env)); ck_run_programs (SYSCONFDIR "/ConsoleKit/run-session.d", action, extra_env); ck_run_programs (LIBDIR "/ConsoleKit/run-session.d", action, extra_env); for (n = 0; extra_env[n] != NULL; n++) { g_free (extra_env[n]); } } void ck_session_dump (CkSession *session, GKeyFile *key_file) { char *s; char *group_name; ConsoleKitSession *cksession; TRACE (); cksession = CONSOLE_KIT_SESSION (session); group_name = g_strdup_printf ("Session %s", session->priv->id); g_key_file_set_integer (key_file, group_name, "uid", console_kit_session_get_unix_user (cksession)); g_key_file_set_string (key_file, group_name, "seat", NONULL_STRING (session->priv->seat_id)); if (console_kit_session_get_session_service (cksession) != NULL) { g_key_file_set_string (key_file, group_name, "service", NONULL_STRING (console_kit_session_get_session_service (cksession))); } if (console_kit_session_get_session_type (cksession) != NULL) { g_key_file_set_string (key_file, group_name, "type", NONULL_STRING (console_kit_session_get_session_type (cksession))); } if (session->priv->login_session_id != NULL && strlen (session->priv->login_session_id) > 0) { g_key_file_set_string (key_file, group_name, "login_session_id", NONULL_STRING (session->priv->login_session_id)); } if (console_kit_session_get_display_device (cksession) != NULL && strlen (console_kit_session_get_display_device (cksession)) > 0) { g_key_file_set_string (key_file, group_name, "display_device", NONULL_STRING (console_kit_session_get_display_device (cksession))); } if (console_kit_session_get_x11_display_device (cksession) != NULL && strlen (console_kit_session_get_x11_display_device (cksession)) > 0) { g_key_file_set_string (key_file, group_name, "x11_display_device", NONULL_STRING (console_kit_session_get_x11_display_device (cksession))); } if (console_kit_session_get_x11_display (cksession) != NULL && strlen (console_kit_session_get_x11_display (cksession)) > 0) { g_key_file_set_string (key_file, group_name, "x11_display", NONULL_STRING (console_kit_session_get_x11_display (cksession))); } if (console_kit_session_get_remote_host_name (cksession) != NULL && strlen (console_kit_session_get_remote_host_name (cksession)) > 0) { g_key_file_set_string (key_file, group_name, "remote_host_name", NONULL_STRING (console_kit_session_get_remote_host_name (cksession))); } g_key_file_set_string (key_file, group_name, "remote_host_name", NONULL_STRING (console_kit_session_get_remote_host_name (cksession))); g_key_file_set_boolean (key_file, group_name, "is_active", console_kit_session_get_active (cksession)); g_key_file_set_boolean (key_file, group_name, "is_local", console_kit_session_get_is_local (cksession)); g_key_file_set_string (key_file, group_name, "XDG_RUNTIME_DIR", NONULL_STRING (session->priv->runtime_dir)); s = g_time_val_to_iso8601 (&(session->priv->creation_time)); g_key_file_set_string (key_file, group_name, "creation_time", NONULL_STRING (s)); g_free (s); g_free (group_name); } consolekit2-1.2.6/src/ck-session.h000066400000000000000000000211221446640754400170060ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_SESSION_H #define __CK_SESSION_H #include #include "ck-session-generated.h" G_BEGIN_DECLS #define CK_TYPE_SESSION (ck_session_get_type ()) #define CK_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_SESSION, CkSession)) #define CK_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_SESSION, CkSessionClass)) #define CK_IS_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_SESSION)) #define CK_IS_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_SESSION)) #define CK_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_SESSION, CkSessionClass)) typedef struct CkSessionPrivate CkSessionPrivate; typedef struct { ConsoleKitSessionSkeleton parent; CkSessionPrivate *priv; } CkSession; typedef struct { /* internal signals */ void (* activate) (CkSession *session, GDBusMethodInvocation *context); ConsoleKitSessionSkeletonClass parent_class; } CkSessionClass; typedef enum { CK_SESSION_ERROR_FAILED, CK_SESSION_ERROR_GENERAL, CK_SESSION_ERROR_INSUFFICIENT_PERMISSION, CK_SESSION_ERROR_NOT_SUPPORTED, CK_SESSION_ERROR_ALREADY_ACTIVE, CK_SESSION_NUM_ERRORS } CkSessionError; #define CK_SESSION_ERROR ck_session_error_quark () GQuark ck_session_error_quark (void); GType ck_session_error_get_type (void); GType ck_session_get_type (void); CkSession * ck_session_new (const char *ssid, const char *cookie, GDBusConnection *connection); CkSession * ck_session_new_with_parameters (const char *ssid, const char *cookie, const GVariant *parameters, GDBusConnection *connection); void ck_session_dump (CkSession *session, GKeyFile *key_file); void ck_session_run_programs (CkSession *session, const char *action); gboolean ck_session_set_active (CkSession *session, gboolean active, gboolean force); gboolean ck_session_set_is_local (CkSession *session, gboolean is_local, GError **error); gboolean ck_session_set_unix_user (CkSession *session, guint uid, GError **error); gboolean ck_session_set_x11_display (CkSession *session, const char *xdisplay, GError **error); gboolean ck_session_set_x11_display_device (CkSession *session, const char *xdisplay, GError **error); gboolean ck_session_set_display_device (CkSession *session, const char *device, GError **error); gboolean ck_session_set_remote_host_name (CkSession *session, const char *remote_host_name, GError **error); gboolean ck_session_set_session_type (CkSession *session, const char *type, GError **error); void ck_session_set_session_controller (CkSession *session, const gchar *bus_name); /* Authoritative properties */ gboolean ck_session_get_id (CkSession *session, char **ssid, GError **error); gboolean ck_session_get_seat_id (CkSession *session, char **sid, GError **error); gboolean ck_session_is_active (CkSession *session, gboolean *active, GError **error); gboolean ck_session_is_local (CkSession *session, gboolean *local, GError **error); gboolean ck_session_get_login_session_id (CkSession *session, char **login_session_id, GError **error); gboolean ck_session_get_creation_time (CkSession *session, char **iso8601_datetime, GError **error); const char * ck_session_get_runtime_dir (CkSession *session); gboolean ck_session_set_runtime_dir (CkSession *session, const char *runtime_dir); gboolean ck_session_set_id (CkSession *session, const char *ssid, GError **error); gboolean ck_session_set_cookie (CkSession *session, const char *cookie, GError **error); gboolean ck_session_set_seat_id (CkSession *session, const char *sid, GError **error); gboolean ck_session_set_login_session_id (CkSession *session, const char *login_session_id, GError **error); void ck_session_lock (CkSession *session); void ck_session_unlock (CkSession *session); G_END_DECLS #endif /* __CK_SESSION_H */ consolekit2-1.2.6/src/ck-sysdeps-dragonfly.c000066400000000000000000000360611446640754400210030ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * Copyright (C) 2007 Joe Marcus Clarke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_SYS_RESOURCE_H #include #endif #include #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_VFS_TMPFS_TMPFS_MOUNT_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #define DEV_ENCODE(M,m) ( \ ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ ) #include "ck-sysdeps.h" #ifndef ERROR #define ERROR -1 #endif /* adapted from procps */ struct _CkProcessStat { int pid; int ppid; /* stat,status pid of parent process */ char state; /* stat,status single-char code for process state (S=sleeping) */ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */ unsigned long long utime; /* stat user-mode CPU time accumulated by process */ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */ unsigned long long cutime; /* stat cumulative utime of process and reaped children */ unsigned long long cstime; /* stat cumulative stime of process and reaped children */ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */ unsigned long start_code; /* stat address of beginning of code segment */ unsigned long end_code; /* stat address of end of code segment */ unsigned long start_stack; /* stat address of the bottom of stack for the process */ unsigned long kstk_esp; /* stat kernel stack pointer */ unsigned long kstk_eip; /* stat kernel instruction pointer */ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */ long priority; /* stat kernel scheduling priority */ long nice; /* stat standard unix nice level of process */ long rss; /* stat resident set size from /proc/#/stat (pages) */ long alarm; /* stat ? */ unsigned long rtprio; /* stat real-time priority */ unsigned long sched; /* stat scheduling class */ unsigned long vsize; /* stat number of pages of virtual memory ... */ unsigned long rss_rlim; /* stat resident set size limit? */ unsigned long flags; /* stat kernel flags for the process */ unsigned long min_flt; /* stat number of minor page faults since process start */ unsigned long maj_flt; /* stat number of major page faults since process start */ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */ int pgrp; /* stat process group id */ int session; /* stat session id */ int nlwp; /* stat number of threads, or 0 if no clue */ int tty; /* stat full device number of controlling terminal */ int tpgid; /* stat terminal process group id */ int exit_signal; /* stat might not be SIGCHLD */ int processor; /* stat current (or most recent?) CPU */ uintptr_t penv; /* stat address of initial environment vector */ char tty_text[16]; /* stat device name */ }; pid_t ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); return stat->ppid; } char * ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup (stat->cmd); } char * ck_process_stat_get_tty (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup_printf ("/dev/%s", stat->tty_text); } static gboolean get_kinfo_proc (pid_t pid, struct kinfo_proc *p) { int mib[4]; size_t len; len = 4; sysctlnametomib ("kern.proc.pid", mib, &len); len = sizeof(struct kinfo_proc); mib[3] = pid; if (sysctl (mib, 4, p, &len, NULL, 0) == -1) { return FALSE; } return TRUE; } /* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct kinfo_proc p; char *ttname; int num; int tty_maj; int tty_min; if (! get_kinfo_proc (pid, &p)) { return FALSE; } num = MAXCOMLEN; if (num >= sizeof P->cmd) { num = sizeof P->cmd - 1; } memcpy (P->cmd, p.kp_comm, num); P->cmd[num] = '\0'; P->pid = p.kp_pid; P->ppid = p.kp_ppid; P->pgrp = p.kp_pgid; P->session = p.kp_sid; P->rss = p.kp_vm_rssize; P->vsize = p.kp_vm_map_size; P->start_time = p.kp_start.tv_sec; P->wchan = (unsigned long) p.kp_lwp.kl_wchan; P->state = p.kp_stat; P->nice = p.kp_nice; P->flags = p.kp_flags; P->tpgid = p.kp_tpgid; P->processor = p.kp_lwp.kl_cpuid; P->nlwp = p.kp_nthreads; /* we like it Linux-encoded :-) */ tty_maj = major (p.kp_tdev); tty_min = minor (p.kp_tdev); P->tty = DEV_ENCODE (tty_maj,tty_min); snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min); if (p.kp_tdev != NODEV && (ttname = devname (p.kp_tdev, S_IFCHR)) != NULL) { memcpy (P->tty_text, ttname, sizeof (P->tty_text)); } if (p.kp_tdev == NODEV) { memcpy (P->tty_text, " ? ", sizeof (P->tty_text)); } if (P->pid != pid) { return FALSE; } return TRUE; } gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error) { gboolean res; CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); if (stat == NULL) { return FALSE; } proc = g_new0 (CkProcessStat, 1); proc->pid = pid; res = stat2proc (pid, proc); if (res) { *stat = proc; } else { *stat = NULL; } return res; } void ck_process_stat_free (CkProcessStat *stat) { g_free (stat); } GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { GHashTable *hash = NULL; char **penv; char errbuf[_POSIX2_LINE_MAX]; kvm_t *kd; struct kinfo_proc p; int i; kd = kvm_openfiles (_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf); if (kd == NULL) { g_warning ("kvm_openfiles failed: %s", errbuf); return NULL; } if (! get_kinfo_proc (pid, &p)) { g_warning ("get_kinfo_proc failed: %s", g_strerror (errno)); goto fail; } penv = kvm_getenvv (kd, &p, 0); if (penv == NULL) { g_warning ("kvm_getenvv failed: %s", kvm_geterr (kd)); goto fail; } hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (i = 0; penv[i] != NULL; i++) { char **vals; if (!penv[i][0]) continue; vals = g_strsplit (penv[i], "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } fail: kvm_close (kd); return hash; } char * ck_unix_pid_get_env (pid_t pid, const char *var) { GHashTable *hash; char *val = NULL; /* * Would probably be more efficient to just loop through the * environment and return the value, avoiding building the hash * table, but this works for now. */ hash = ck_unix_pid_get_env_hash (pid); if (hash == NULL) return val; val = g_strdup (g_hash_table_lookup (hash, var)); g_hash_table_destroy (hash); return val; } uid_t ck_unix_pid_get_uid (pid_t pid) { uid_t uid; gboolean res; struct kinfo_proc p; g_return_val_if_fail (pid > 1, 0); uid = -1; res = get_kinfo_proc (pid, &p); if (res) { uid = p.kp_uid; } return uid; } gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **idp) { g_return_val_if_fail (pid > 1, FALSE); return FALSE; } gboolean ck_get_max_num_consoles (guint *num) { guint max_consoles; guint i; glob_t g; max_consoles = 0; g.gl_offs = 0; glob ("/dev/ttyv*", GLOB_DOOFFS | GLOB_NOSORT, NULL, &g); for (i = 0; i < g.gl_pathc && g.gl_pathv[i] != NULL; i++) { struct stat sb; char *cdev; cdev = g.gl_pathv[i]; if (stat (cdev, &sb) > -1 && S_ISCHR (sb.st_mode)) { max_consoles++; } else { break; } } globfree (&g); /* * Increment one more so that all consoles are properly counted * this is arguable a bug in vt_add_watches(). */ max_consoles++; if (num != NULL) { *num = max_consoles; } return TRUE; } gboolean ck_supports_activatable_consoles (void) { return TRUE; } char * ck_get_console_device_for_num (guint num) { char *device; /* The device number is always one less than the VT number. */ num--; if (num < 10) device = g_strdup_printf ("/dev/ttyv%i", num); else if (num < 32) device = g_strdup_printf ("/dev/ttyv%c", num - 10 + 'a'); else device = NULL; return device; } gboolean ck_get_console_num_from_device (const char *device, guint *num) { guint n; char c; gboolean ret; n = 0; ret = FALSE; if (device == NULL) { return FALSE; } if (sscanf (device, "/dev/ttyv%c", &c) == 1) { if (c < 58) n = c - 48; else n = c - 'a' + 10; /* The VT number is always one more than the device number. */ n++; ret = TRUE; } if (num != NULL) { *num = n; } return ret; } gboolean ck_get_active_console_num (int console_fd, guint *num) { gboolean ret; int res; int active; char ttyn; g_assert (console_fd != -1); active = 0; ret = FALSE; res = ioctl (console_fd, VT_GETACTIVE, &active); if (res == ERROR) { perror ("ioctl VT_GETACTIVE"); goto out; } if (active - 1 < 10) ttyn = active - 1 + '0'; else ttyn = active - 11 + 'a'; g_debug ("Active VT is: %d (ttyv%c)", active, ttyn); ret = TRUE; out: if (num != NULL) { *num = active; } return ret; } /* DragonFly has no support for suspend, hibernate, or sleep */ gboolean ck_system_can_suspend (void) { return FALSE; } gboolean ck_system_can_hibernate (void) { return FALSE; } gboolean ck_system_can_hybrid_sleep (void) { return FALSE; } gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest) { #ifdef HAVE_VFS_TMPFS_TMPFS_MOUNT_H int result; struct tmpfs_mount_info opts; TRACE (); opts.ta_version = TMPFS_ARGS_VERSION; opts.ta_size_max = 0; opts.ta_nodes_max = 0; opts.ta_maxfsize_max = 0; opts.ta_root_uid = uid; opts.ta_root_gid = gid; opts.ta_root_mode = 0x1c0; /* 0700 */ result = mount("tmpfs", dest, 0, &opts); if (result == 0) { return TRUE; } else { g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno)); errno = 0; return FALSE; } #endif return FALSE; } gboolean ck_remove_tmpfs (guint uid, const gchar *dest) { #ifdef HAVE_VFS_TMPFS_TMPFS_MOUNT_H int result; TRACE (); result = unmount(dest, 0); if (result == 0) { return TRUE; } g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno)); errno = 0; #endif return FALSE; } gboolean ck_sysdeps_init (void) { return TRUE; } void ck_sysdeps_fini (void) { } consolekit2-1.2.6/src/ck-sysdeps-freebsd.c000066400000000000000000000377471446640754400204440ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * Copyright (C) 2007 Joe Marcus Clarke * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_SYS_RESOURCE_H #include #endif #include #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #define DEV_ENCODE(M,m) ( \ ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ ) #include "ck-sysdeps.h" #ifndef ERROR #define ERROR -1 #endif /* adapted from procps */ struct _CkProcessStat { int pid; int ppid; /* stat,status pid of parent process */ char state; /* stat,status single-char code for process state (S=sleeping) */ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */ unsigned long long utime; /* stat user-mode CPU time accumulated by process */ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */ unsigned long long cutime; /* stat cumulative utime of process and reaped children */ unsigned long long cstime; /* stat cumulative stime of process and reaped children */ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */ unsigned long start_code; /* stat address of beginning of code segment */ unsigned long end_code; /* stat address of end of code segment */ unsigned long start_stack; /* stat address of the bottom of stack for the process */ unsigned long kstk_esp; /* stat kernel stack pointer */ unsigned long kstk_eip; /* stat kernel instruction pointer */ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */ long priority; /* stat kernel scheduling priority */ long nice; /* stat standard unix nice level of process */ long rss; /* stat resident set size from /proc/#/stat (pages) */ long alarm; /* stat ? */ unsigned long rtprio; /* stat real-time priority */ unsigned long sched; /* stat scheduling class */ unsigned long vsize; /* stat number of pages of virtual memory ... */ unsigned long rss_rlim; /* stat resident set size limit? */ unsigned long flags; /* stat kernel flags for the process */ unsigned long min_flt; /* stat number of minor page faults since process start */ unsigned long maj_flt; /* stat number of major page faults since process start */ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */ int pgrp; /* stat process group id */ int session; /* stat session id */ int nlwp; /* stat number of threads, or 0 if no clue */ int tty; /* stat full device number of controlling terminal */ int tpgid; /* stat terminal process group id */ int exit_signal; /* stat might not be SIGCHLD */ int processor; /* stat current (or most recent?) CPU */ uintptr_t penv; /* stat address of initial environment vector */ char tty_text[16]; /* stat device name */ }; pid_t ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); return stat->ppid; } char * ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup (stat->cmd); } char * ck_process_stat_get_tty (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup_printf ("/dev/%s", stat->tty_text); } static gboolean get_kinfo_proc (pid_t pid, struct kinfo_proc *p) { int mib[4]; size_t len; len = 4; sysctlnametomib ("kern.proc.pid", mib, &len); len = sizeof(struct kinfo_proc); mib[3] = pid; if (sysctl (mib, 4, p, &len, NULL, 0) == -1) { return FALSE; } return TRUE; } /* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct kinfo_proc p; char *ttname; guint num; int tty_maj; int tty_min; if (! get_kinfo_proc (pid, &p)) { return FALSE; } num = OCOMMLEN; if (num >= sizeof P->cmd) { num = sizeof P->cmd - 1; } memcpy (P->cmd, p.ki_ocomm, num); P->cmd[num] = '\0'; P->pid = p.ki_pid; P->ppid = p.ki_ppid; P->pgrp = p.ki_pgid; P->session = p.ki_sid; P->rss = p.ki_rssize; P->vsize = p.ki_size; P->start_time = p.ki_start.tv_sec; P->wchan = (unsigned long) p.ki_wchan; P->state = p.ki_stat; P->nice = p.ki_nice; P->flags = p.ki_sflag; P->tpgid = p.ki_tpgid; P->processor = p.ki_oncpu; P->nlwp = p.ki_numthreads; /* we like it Linux-encoded :-) */ tty_maj = major (p.ki_tdev); tty_min = minor (p.ki_tdev); P->tty = DEV_ENCODE (tty_maj,tty_min); snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min); if (p.ki_tdev != NODEV && (ttname = devname (p.ki_tdev, S_IFCHR)) != NULL) { memcpy (P->tty_text, ttname, sizeof (P->tty_text)); } if (p.ki_tdev == NODEV) { memcpy (P->tty_text, " ? ", sizeof (P->tty_text)); } if (P->pid != pid) { return FALSE; } return TRUE; } gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error) { gboolean res; CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); if (stat == NULL) { return FALSE; } proc = g_new0 (CkProcessStat, 1); proc->pid = pid; res = stat2proc (pid, proc); if (res) { *stat = proc; } else { *stat = NULL; } return res; } void ck_process_stat_free (CkProcessStat *stat) { g_free (stat); } GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { GHashTable *hash = NULL; char **penv; char errbuf[_POSIX2_LINE_MAX]; kvm_t *kd; struct kinfo_proc p; int i; kd = kvm_openfiles (_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf); if (kd == NULL) { g_warning ("kvm_openfiles failed: %s", errbuf); return NULL; } if (! get_kinfo_proc (pid, &p)) { g_warning ("get_kinfo_proc failed: %s", g_strerror (errno)); goto fail; } penv = kvm_getenvv (kd, &p, 0); if (penv == NULL) { g_warning ("kvm_getenvv failed: %s", kvm_geterr (kd)); goto fail; } hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (i = 0; penv[i] != NULL; i++) { char **vals; if (!penv[i][0]) continue; vals = g_strsplit (penv[i], "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } fail: kvm_close (kd); return hash; } char * ck_unix_pid_get_env (pid_t pid, const char *var) { GHashTable *hash; char *val = NULL; /* * Would probably be more efficient to just loop through the * environment and return the value, avoiding building the hash * table, but this works for now. */ hash = ck_unix_pid_get_env_hash (pid); if (hash == NULL) return val; val = g_strdup (g_hash_table_lookup (hash, var)); g_hash_table_destroy (hash); return val; } uid_t ck_unix_pid_get_uid (pid_t pid) { uid_t uid; gboolean res; struct kinfo_proc p; g_return_val_if_fail (pid > 1, 0); uid = -1; res = get_kinfo_proc (pid, &p); if (res) { uid = p.ki_uid; } return uid; } gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **idp) { g_return_val_if_fail (pid > 1, FALSE); return FALSE; } gboolean ck_get_max_num_consoles (guint *num) { guint max_consoles; guint i; glob_t g; max_consoles = 0; g.gl_offs = 0; glob ("/dev/ttyv*", GLOB_DOOFFS | GLOB_NOSORT, NULL, &g); for (i = 0; i < g.gl_pathc && g.gl_pathv[i] != NULL; i++) { struct stat sb; char *cdev; cdev = g.gl_pathv[i]; if (stat (cdev, &sb) > -1 && S_ISCHR (sb.st_mode)) { max_consoles++; } else { break; } } globfree (&g); /* * Increment one more so that all consoles are properly counted * this is arguable a bug in vt_add_watches(). */ max_consoles++; if (num != NULL) { *num = max_consoles; } return TRUE; } gboolean ck_supports_activatable_consoles (void) { return TRUE; } char * ck_get_console_device_for_num (guint num) { char *device; /* The device number is always one less than the VT number. */ num--; if (num < 10) device = g_strdup_printf ("/dev/ttyv%i", num); else if (num < 32) device = g_strdup_printf ("/dev/ttyv%c", num - 10 + 'a'); else device = NULL; return device; } gboolean ck_get_console_num_from_device (const char *device, guint *num) { guint n; char c; gboolean ret; n = 0; ret = FALSE; if (device == NULL) { return FALSE; } if (sscanf (device, "/dev/ttyv%c", &c) == 1) { if (c < 58) n = c - 48; else n = c - 'a' + 10; /* The VT number is always one more than the device number. */ n++; ret = TRUE; } if (num != NULL) { *num = n; } return ret; } gboolean ck_get_active_console_num (int console_fd, guint *num) { gboolean ret; int res; int active; char ttyn; g_assert (console_fd != -1); active = 0; ret = FALSE; res = ioctl (console_fd, VT_GETACTIVE, &active); if (res == ERROR) { perror ("ioctl VT_GETACTIVE"); goto out; } if (active - 1 < 10) ttyn = active - 1 + '0'; else ttyn = active - 11 + 'a'; g_debug ("Active VT is: %d (ttyv%c)", active, ttyn); ret = TRUE; out: if (num != NULL) { *num = active; } return ret; } static gchar * get_string_sysctl (GError **err, const gchar *format, ...) { va_list args; gchar *name; size_t value_len; gchar *str = NULL; g_return_val_if_fail(format != NULL, FALSE); va_start (args, format); name = g_strdup_vprintf (format, args); va_end (args); if (sysctlbyname (name, NULL, &value_len, NULL, 0) == 0) { str = g_new (char, value_len + 1); if (sysctlbyname (name, str, &value_len, NULL, 0) == 0) { str[value_len] = 0; } else { g_free (str); str = NULL; } } if (!str) g_set_error (err, 0, 0, "%s", g_strerror(errno)); g_free(name); return str; } static gboolean freebsd_supports_sleep_state (const gchar *state) { gboolean ret = FALSE; gchar *sleep_states; sleep_states = get_string_sysctl (NULL, "hw.acpi.supported_sleep_state"); if (sleep_states != NULL) { if (strstr (sleep_states, state) != NULL) ret = TRUE; } g_free (sleep_states); return ret; } gboolean ck_system_can_suspend (void) { return freebsd_supports_sleep_state ("S3"); } gboolean ck_system_can_hibernate (void) { return freebsd_supports_sleep_state ("S4"); } gboolean ck_system_can_hybrid_sleep (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest) { #ifdef HAVE_SYS_MOUNT_H gchar *opts; int result; TRACE (); opts = g_strdup_printf ("mode=0700,uid=%d", uid); result = mount("tmpfs", dest, 0, opts); g_free (opts); if (result == 0) { return TRUE; } else { g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno)); errno = 0; return FALSE; } #endif return FALSE; } gboolean ck_remove_tmpfs (guint uid, const gchar *dest) { #ifdef HAVE_SYS_MOUNT_H int result; TRACE (); result = unmount(dest, 0); if (result == 0) { return TRUE; } g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno)); errno = 0; #endif return FALSE; } gboolean ck_sysdeps_init (void) { return TRUE; } void ck_sysdeps_fini (void) { } consolekit2-1.2.6/src/ck-sysdeps-gnu.c000066400000000000000000000233301446640754400176020ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2009 Pino Toscano * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif /* HAVE_PATHS_H */ #include "ck-sysdeps.h" struct _CkProcessStat { struct proc_stat *ps; /* the statistics of a process */ }; static struct ps_context *pc = NULL; static gboolean get_proc_stat_from_pid (pid_t pid, ps_flags_t flags, struct proc_stat **res_ps) { error_t err; struct proc_stat *ps; g_assert (pid >= 0); g_assert (res_ps != NULL); if (pc == NULL) { err = ps_context_create (getproc (), &pc); if (err) { return FALSE; } } err = _proc_stat_create (pid, pc, &ps); if (err) { return FALSE; } err = proc_stat_set_flags (ps, PSTAT_PID | flags); if (err) { return FALSE; } *res_ps = ps; return TRUE; } pid_t ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); return proc_stat_pid (stat->ps); } char * ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup (proc_stat_args (stat->ps)); } char * ck_process_stat_get_tty (CkProcessStat *stat) { struct ps_tty *tty; g_return_val_if_fail (stat != NULL, NULL); tty = proc_stat_tty (stat->ps); return tty ? g_strdup (ps_tty_name (tty)) : NULL; } gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error) { gboolean res; struct proc_stat *ps; CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); if (stat == NULL) { return FALSE; } *stat = NULL; res = get_proc_stat_from_pid (pid, PSTAT_ARGS | PSTAT_TTY, &ps); if (!res) { return FALSE; } proc = g_new0 (CkProcessStat, 1); proc->ps = ps; *stat = proc; return TRUE; } void ck_process_stat_free (CkProcessStat *stat) { _proc_stat_free (stat->ps); g_free (stat); } GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { struct proc_stat *ps; char *env_p; size_t env_index; size_t env_l; gboolean res; GHashTable *hash; g_return_val_if_fail (pid > 1, NULL); res = get_proc_stat_from_pid (pid, PSTAT_ENV, &ps); if (!res) { return NULL; } hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); env_index = 0; env_l = 0; env_p = proc_stat_env (ps); while (env_index < proc_stat_env_len (ps)) { env_l = strlen (env_p); env_index += env_l + 1; if (env_l) { char **vals; vals = g_strsplit (env_p, "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } env_p = env_p + env_l + 1; } _proc_stat_free (ps); return hash; } char * ck_unix_pid_get_env (pid_t pid, const char *var) { struct proc_stat *ps; char *env_p; size_t env_index; size_t env_l; char *prefix; int prefix_len; char *val; gboolean res; g_return_val_if_fail (pid > 1, NULL); val = NULL; res = get_proc_stat_from_pid (pid, PSTAT_ENV, &ps); if (!res) { return NULL; } prefix = g_strdup_printf ("%s=", var); prefix_len = strlen (prefix); env_index = 0; env_l = 0; env_p = proc_stat_env (ps); while (env_index < proc_stat_env_len (ps)) { env_l = strlen (env_p); env_index += env_l + 1; if (env_l && g_str_has_prefix (env_p, prefix)) { val = g_strdup (env_p + prefix_len); break; } env_p = env_p + env_l + 1; } g_free (prefix); _proc_stat_free (ps); return val; } uid_t ck_unix_pid_get_uid (pid_t pid) { struct proc_stat *ps; gboolean res; uid_t uid; g_return_val_if_fail (pid > 1, 0); res = get_proc_stat_from_pid (pid, PSTAT_OWNER_UID, &ps); if (!res) { return 0; } uid = proc_stat_owner_uid (ps); _proc_stat_free (ps); return uid; } pid_t ck_unix_pid_get_ppid (pid_t pid) { struct proc_stat *ps; gboolean res; pid_t ppid; g_return_val_if_fail (pid > 1, 0); res = get_proc_stat_from_pid (pid, PSTAT_PROC_INFO, &ps); if (!res) { return 0; } ppid = proc_stat_proc_info (ps)->ppid; _proc_stat_free (ps); return ppid; } gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **idp) { g_return_val_if_fail (pid > 1, FALSE); return FALSE; } gboolean ck_get_max_num_consoles (guint *num) { int max_consoles; int res; gboolean ret; struct ttyent *t; ret = FALSE; max_consoles = 0; res = setttyent (); if (res == 0) { goto done; } while ((t = getttyent ()) != NULL) { if (t->ty_status & TTY_ON && strncmp (t->ty_name, "tty", 3) == 0) max_consoles++; } /* Increment one more so that all consoles are properly counted * this is arguable a bug in vt_add_watches(). */ max_consoles++; ret = TRUE; endttyent (); done: if (num != NULL) { *num = max_consoles; } return ret; } gboolean ck_supports_activatable_consoles (void) { return TRUE; } char * ck_get_console_device_for_num (guint num) { char *device; device = g_strdup_printf (_PATH_TTY "%u", num); return device; } gboolean ck_get_console_num_from_device (const char *device, guint *num) { guint n; gboolean ret; n = 0; ret = FALSE; if (device == NULL) { return FALSE; } if (sscanf (device, _PATH_TTY "%u", &n) == 1) { ret = TRUE; } if (num != NULL) { *num = n; } return ret; } gboolean ck_get_active_console_num (int console_fd, guint *num) { gboolean ret; int res; long cur_active; char buf[30]; guint active; g_assert (console_fd != -1); active = 0; ret = FALSE; res = readlink ("/dev/cons/vcs", buf, sizeof (buf)); if (res > 0) { /* the resolved path is like "/dev/vcs/$number", so skip the non-number part at the start */ const char *p = buf; while ((*p) && ((*p < '0') || (*p > '9'))) { ++p; } if (*p) { cur_active = strtol (p, NULL, 10); g_debug ("Current VT: tty%ld", cur_active); active = cur_active; ret = TRUE; } } if (num != NULL) { *num = active; } return ret; } gboolean ck_system_can_suspend (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_system_can_hibernate (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_system_can_hybrid_sleep (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest) { return FALSE; } gboolean ck_remove_tmpfs (guint uid, const gchar *dest) { return FALSE; } gboolean ck_sysdeps_init (void) { return TRUE; } void ck_sysdeps_fini (void) { } consolekit2-1.2.6/src/ck-sysdeps-linux.c000066400000000000000000001023171446640754400201530ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif /* HAVE_PATHS_H */ #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SELINUX #include #include #include #include #endif #include "ck-sysdeps.h" #ifndef ERROR #define ERROR -1 #endif /* adapted from procps */ struct _CkProcessStat { int pid; int ppid; /* stat,status pid of parent process */ char state; /* stat,status single-char code for process state (S=sleeping) */ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */ unsigned long long utime; /* stat user-mode CPU time accumulated by process */ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */ unsigned long long cutime; /* stat cumulative utime of process and reaped children */ unsigned long long cstime; /* stat cumulative stime of process and reaped children */ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */ unsigned long start_code; /* stat address of beginning of code segment */ unsigned long end_code; /* stat address of end of code segment */ unsigned long start_stack; /* stat address of the bottom of stack for the process */ unsigned long kstk_esp; /* stat kernel stack pointer */ unsigned long kstk_eip; /* stat kernel instruction pointer */ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */ long priority; /* stat kernel scheduling priority */ long nice; /* stat standard unix nice level of process */ long rss; /* stat resident set size from /proc/#/stat (pages) */ long alarm; /* stat ? */ unsigned long rtprio; /* stat real-time priority */ unsigned long sched; /* stat scheduling class */ unsigned long vsize; /* stat number of pages of virtual memory ... */ unsigned long rss_rlim; /* stat resident set size limit? */ unsigned long flags; /* stat kernel flags for the process */ unsigned long min_flt; /* stat number of minor page faults since process start */ unsigned long maj_flt; /* stat number of major page faults since process start */ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */ int pgrp; /* stat process group id */ int session; /* stat session id */ int nlwp; /* stat number of threads, or 0 if no clue */ int tty; /* stat full device number of controlling terminal */ int tpgid; /* stat terminal process group id */ int exit_signal; /* stat might not be SIGCHLD */ int processor; /* stat current (or most recent?) CPU */ }; /* adapted from procps */ #define MAJOR_OF(d) ( ((unsigned)(d)>>8u) & 0xfffu ) #define MINOR_OF(d) ( ((unsigned)(d)&0xffu) | (((unsigned)(d)&0xfff00000u)>>12u) ) typedef struct tty_map_node { struct tty_map_node *next; guint major_number; guint minor_first; guint minor_last; char name[32]; char devfs_type; } tty_map_node; static tty_map_node *tty_map = NULL; #ifdef HAVE_SELINUX static struct selabel_handle *label_hnd = NULL; #endif /* adapted from procps */ /* Load /proc/tty/drivers for device name mapping use. */ static void load_drivers (void) { char buf[10000]; char *p; int fd; int bytes; fd = open ("/proc/tty/drivers", O_RDONLY); if (fd == -1) { goto fail; } bytes = read (fd, buf, sizeof (buf) - 1); if (bytes == -1) { goto fail; } buf[bytes] = '\0'; p = buf; while ((p = strstr (p, " " _PATH_DEV))) { tty_map_node *tmn; int len; char *end; p += 6; end = strchr (p, ' '); if (! end) { continue; } len = end - p; tmn = calloc (1, sizeof (tty_map_node)); tmn->next = tty_map; tty_map = tmn; /* if we have a devfs type name such as /dev/tts/%d then strip the %d but keep a flag. */ if (len >= 3 && !strncmp (end - 2, "%d", 2)) { len -= 2; tmn->devfs_type = 1; } strncpy (tmn->name, p, len); p = end; /* set p to point past the %d as well if there is one */ while (*p == ' ') { p++; } tmn->major_number = atoi (p); p += strspn (p, "0123456789"); while (*p == ' ') { p++; } switch (sscanf (p, "%u-%u", &tmn->minor_first, &tmn->minor_last)) { default: /* Can't finish parsing this line so we remove it from the list */ tty_map = tty_map->next; free (tmn); break; case 1: tmn->minor_last = tmn->minor_first; break; case 2: break; } } fail: if (fd != -1) { close (fd); } if(! tty_map) { tty_map = (tty_map_node *)-1; } } /* adapted from procps */ /* Try to guess the device name from /proc/tty/drivers info. */ static char * driver_name (guint maj, guint min) { struct stat sbuf; tty_map_node *tmn; char *tty; if (! tty_map) { load_drivers (); } if (tty_map == (tty_map_node *) - 1) { return 0; } tmn = tty_map; for (;;) { if (! tmn) { return 0; } if (tmn->major_number == maj && tmn->minor_first <= min && tmn->minor_last >= min) { break; } tmn = tmn->next; } tty = g_strdup_printf (_PATH_DEV "%s%d", tmn->name, min); /* like "/dev/ttyZZ255" */ if (stat (tty, &sbuf) < 0){ g_free (tty); if (tmn->devfs_type) { return NULL; } tty = g_strdup_printf (_PATH_DEV "%s", tmn->name); /* like "/dev/ttyZZ255" */ if (stat (tty, &sbuf) < 0) { g_free (tty); return NULL; } } if (min != MINOR_OF (sbuf.st_rdev)) { g_free (tty); return NULL; } if (maj != MAJOR_OF (sbuf.st_rdev)) { g_free (tty); return NULL; } return tty; } /* adapted from procps */ static char * link_name (guint maj, guint min, int pid, const char *name) { struct stat sbuf; char *path; char *tty; path = g_strdup_printf ("/proc/%d/%s", pid, name); tty = g_file_read_link (path, NULL); g_free (path); if (tty == NULL) { goto out; } if (stat (tty, &sbuf) < 0) { g_free (tty); tty = NULL; goto out; } if (min != MINOR_OF (sbuf.st_rdev)) { g_free (tty); tty = NULL; goto out; } if (maj != MAJOR_OF (sbuf.st_rdev)) { g_free (tty); tty = NULL; goto out; } out: return tty; } pid_t ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); return stat->ppid; } char * ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup (stat->cmd); } /* adapted from procps */ char * ck_process_stat_get_tty (CkProcessStat *stat) { guint dev; char *tty; guint dev_maj; guint dev_min; pid_t pid; g_return_val_if_fail (stat != NULL, NULL); pid = stat->pid; dev = stat->tty; if (dev == 0u) { return NULL; } dev_maj = MAJOR_OF (dev); dev_min = MINOR_OF (dev); tty = link_name (dev_maj, dev_min, pid, "tty"); if (tty != NULL) { goto out; } tty = driver_name (dev_maj, dev_min); if (tty != NULL) { goto out; } tty = link_name (dev_maj, dev_min, pid, "fd/2"); if (tty != NULL) { goto out; } tty = link_name (dev_maj, dev_min, pid, "fd/255"); if (tty != NULL) { goto out; } out: return tty; } #define KLF "l" /* adapted from procps */ static void stat2proc (const char *S, CkProcessStat *P) { unsigned num; char * tmp; /* fill in default values for older kernels */ P->processor = 0; P->rtprio = -1; P->sched = -1; P->nlwp = 0; S = strchr (S, '(') + 1; tmp = strrchr (S, ')'); num = tmp - S; if (G_UNLIKELY (num >= sizeof P->cmd)) { num = sizeof P->cmd - 1; } memcpy (P->cmd, S, num); P->cmd[num] = '\0'; S = tmp + 2; /* skip ") " */ num = sscanf (S, "%c " /* state */ "%d %d %d %d %d " /* ppid pgrp session tty tpgid */ "%lu %lu %lu %lu %lu " /* flags min_flt cmin_flt maj_flt cmaj_flt */ "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ "%ld %ld " /* priority nice*/ "%d " /* nlwp */ "%ld " /* alarm */ "%Lu " /* start_time */ "%lu " /* vsize */ "%ld " /* rss */ "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u " /* rss_rlim start_code end_code start_stack kstk_esp kstk_eip */ "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ "%"KLF"u %*u %*u " /* wchan */ "%d %d " /* exit_signal processor */ "%lu %lu", /* rtprio sched */ &P->state, &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid, &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, &P->utime, &P->stime, &P->cutime, &P->cstime, &P->priority, &P->nice, &P->nlwp, &P->alarm, &P->start_time, &P->vsize, &P->rss, &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip, /* P->signal, P->blocked, P->sigignore, P->sigcatch, */ /* can't use */ &P->wchan, /* &P->nswap, &P->cnswap, */ /* nswap and cnswap dead for 2.4.xx and up */ /* -- Linux 2.0.35 ends here -- */ &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */ /* -- Linux 2.2.8 to 2.5.17 end here -- */ &P->rtprio, &P->sched /* both added to 2.5.18 */ ); if (!P->nlwp){ P->nlwp = 1; } } gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error) { char *path; char *contents; gsize length; gboolean res; GError *local_error; CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); if (stat == NULL) { return FALSE; } path = g_strdup_printf ("/proc/%d/stat", pid); contents = NULL; local_error = NULL; res = g_file_get_contents (path, &contents, &length, &local_error); if (res) { proc = g_new0 (CkProcessStat, 1); proc->pid = pid; stat2proc (contents, proc); *stat = proc; } else { g_propagate_error (error, local_error); *stat = NULL; } g_free (contents); g_free (path); return res; } void ck_process_stat_free (CkProcessStat *stat) { g_free (stat); } GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { char *path; gboolean res; char *contents; gsize length; GError *error; GHashTable *hash; gsize i; gboolean last_was_null; g_return_val_if_fail (pid > 1, NULL); contents = NULL; hash = NULL; path = g_strdup_printf ("/proc/%u/environ", (guint)pid); error = NULL; res = g_file_get_contents (path, &contents, &length, &error); if (! res) { /* This is pretty harmless, usually it means the process * was short lived and we didn't get around to looking at * it before it died. */ g_debug ("Couldn't read %s: %s", path, error->message); g_error_free (error); goto out; } hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); last_was_null = TRUE; for (i = 0; i < length; i++) { if (contents[i] == '\0') { last_was_null = TRUE; continue; } if (last_was_null) { char **vals; vals = g_strsplit (contents + i, "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } last_was_null = FALSE; } out: g_free (contents); g_free (path); return hash; } char * ck_unix_pid_get_env (pid_t pid, const char *var) { char *path; gboolean res; char *contents; char *val; gsize length; GError *error; guint i; char *prefix; int prefix_len; gboolean last_was_null; g_return_val_if_fail (pid > 1, NULL); val = NULL; contents = NULL; prefix = NULL; path = g_strdup_printf ("/proc/%u/environ", (guint)pid); error = NULL; res = g_file_get_contents (path, &contents, &length, &error); if (! res) { g_debug ("Couldn't read %s: %s", path, error->message); g_error_free (error); goto out; } prefix = g_strdup_printf ("%s=", var); prefix_len = strlen (prefix); /* FIXME: make more robust */ last_was_null = TRUE; for (i = 0; i < length; i++) { if (contents[i] == '\0') { last_was_null = TRUE; continue; } if (last_was_null && g_str_has_prefix (contents + i, prefix)) { val = g_strdup (contents + i + prefix_len); break; } last_was_null = FALSE; } out: g_free (prefix); g_free (contents); g_free (path); return val; } uid_t ck_unix_pid_get_uid (pid_t pid) { struct stat st; char *path; int uid; int res; g_return_val_if_fail (pid > 1, 0); uid = -1; path = g_strdup_printf ("/proc/%u", (guint)pid); res = stat (path, &st); g_free (path); if (res == 0) { uid = st.st_uid; } return uid; } pid_t ck_unix_pid_get_ppid (pid_t pid) { int ppid; gboolean res; CkProcessStat *stat; g_return_val_if_fail (pid > 1, 0); ppid = -1; res = ck_process_stat_new_for_unix_pid (pid, &stat, NULL); if (! res) { goto out; } ppid = ck_process_stat_get_ppid (stat); ck_process_stat_free (stat); out: return ppid; } gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **idp) { gboolean ret; gboolean res; char *path; char *contents; gsize length; GError *error; char *end_of_valid_ulong; gulong ulong_value; g_return_val_if_fail (pid > 1, FALSE); ret = FALSE; contents = NULL; path = g_strdup_printf ("/proc/%u/sessionid", (guint)pid); error = NULL; res = g_file_get_contents (path, &contents, &length, &error); if (! res) { g_debug ("Couldn't read %s: %s", path, error->message); g_error_free (error); goto out; } if (contents[0] == '\0') { g_debug ("Couldn't read %s: empty file", path); goto out; } errno = 0; ulong_value = strtoul (contents, &end_of_valid_ulong, 10); if (*end_of_valid_ulong != '\0') { goto out; } if (errno == ERANGE) { g_debug ("Couldn't read %s: %s", path, g_strerror (errno)); goto out; } /* Will be G_MAXUINT32 if it isn't set */ if (ulong_value == G_MAXUINT32) { goto out; } if (idp != NULL) { *idp = g_strdup_printf ("%lu", (unsigned long int)ulong_value); } ret = TRUE; out: g_free (contents); g_free (path); return ret; } gboolean ck_get_max_num_consoles (guint *num) { if (num != NULL) { *num = MAX_NR_CONSOLES; } return TRUE; } gboolean ck_supports_activatable_consoles (void) { return TRUE; } char * ck_get_console_device_for_num (guint num) { char *device; device = g_strdup_printf (_PATH_TTY "%u", num); return device; } gboolean ck_get_console_num_from_device (const char *device, guint *num) { guint n; gboolean ret; n = 0; ret = FALSE; if (device == NULL) { return FALSE; } if (sscanf (device, _PATH_TTY "%u", &n) == 1) { ret = TRUE; } if (num != NULL) { *num = n; } return ret; } gboolean ck_get_active_console_num (int console_fd, guint *num) { gboolean ret; int res; guint active; struct vt_stat stat; g_assert (console_fd != -1); active = 0; ret = FALSE; res = ioctl (console_fd, VT_GETSTATE, &stat); if (res == ERROR) { perror ("ioctl VT_GETSTATE"); goto out; } { int i; g_debug ("Current VT: tty%d", stat.v_active); for (i = 1; i <= 16; i++) { gboolean is_on; is_on = stat.v_state & (1 << i); g_debug ("VT %d:%s", i, is_on ? "on" : "off"); } } active = stat.v_active; ret = TRUE; out: if (num != NULL) { *num = active; } return ret; } /* adapted from upower-0.9 branch */ static gfloat linux_get_used_swap (void) { gchar *contents = NULL; gchar **lines = NULL; GError *error = NULL; gchar **tokens; gboolean ret; guint active = 0; guint swap_free = 0; guint swap_total = 0; guint len; guint i; gfloat percentage = 0.0f; const gchar *filename = "/proc/meminfo"; /* get memory data */ ret = g_file_get_contents (filename, &contents, NULL, &error); if (!ret) { g_debug ("failed to open %s: %s", filename, error->message); g_error_free (error); goto out; } /* process each line */ lines = g_strsplit (contents, "\n", -1); for (i=1; lines[i] != NULL; i++) { tokens = g_strsplit_set (lines[i], ": ", -1); len = g_strv_length (tokens); if (len > 3) { if (g_strcmp0 (tokens[0], "SwapFree") == 0) swap_free = atoi (tokens[len-2]); if (g_strcmp0 (tokens[0], "SwapTotal") == 0) swap_total = atoi (tokens[len-2]); else if (g_strcmp0 (tokens[0], "Active(anon)") == 0) active = atoi (tokens[len-2]); } g_strfreev (tokens); } /* first check if we even have swap, if not consider all swap space used */ if (swap_total == 0) { g_debug ("no swap space found"); percentage = 100.0f; goto out; } /* work out how close to the line we are */ if (swap_free > 0 && active > 0) percentage = (active * 100) / swap_free; g_debug ("total swap available %i kb, active memory %i kb (%.1f%%)", swap_free, active, percentage); out: g_free (contents); g_strfreev (lines); return percentage; } /* adapted from upower-0.9 branch */ static gboolean linux_check_enough_swap (void) { gfloat waterline = 98.0f; /* 98% */ gfloat used_swap = linux_get_used_swap(); if (used_swap < waterline) { g_debug ("enough swap to hibernate"); return TRUE; } else { g_debug ("not enough swap to hibernate"); return FALSE; } g_debug ("should not hit this in linux_check_enough_swap"); return FALSE; } static gboolean linux_supports_sleep_state (const gchar *state) { gboolean ret = FALSE; gchar *command; GError *error = NULL; gint exit_status; command = g_strdup_printf ("grep -q %s /sys/power/state", state); g_debug ("executing command: %s", command); ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error); if (!ret) { g_debug ("failed to run script: %s", error->message); g_error_free (error); goto out; } ret = (WIFEXITED(exit_status) && (WEXITSTATUS(exit_status) == EXIT_SUCCESS)); out: g_free (command); return ret; } gboolean ck_system_can_suspend (void) { return linux_supports_sleep_state ("mem"); } gboolean ck_system_can_hibernate (void) { if (linux_supports_sleep_state ("disk")) return linux_check_enough_swap() ; return FALSE; } gboolean ck_system_can_hybrid_sleep (void) { /* hybrid suspend will create the hibernation image as a fallback, then suspend to RAM */ return (linux_supports_sleep_state ("disk") & linux_supports_sleep_state("mem")); } static gboolean ck_selinux_open(void) { #ifdef HAVE_SELINUX TRACE (); if (label_hnd) return TRUE; if (is_selinux_enabled() <= 0) return TRUE; label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); if (label_hnd) { return TRUE; } else { g_info ("Failed to open selabel handle, reason was: %s", strerror(errno)); errno = 0; // do not fail in permissive mode return (security_getenforce() == 1) ? FALSE : TRUE; } #endif return TRUE; } static void ck_selinux_close(void) { #ifdef HAVE_SELINUX if (label_hnd) { selabel_close(label_hnd); label_hnd = NULL; } #endif } static gchar* ck_selinux_lookup_context(const gchar *dest) { #ifdef HAVE_SELINUX int rc; GStatBuf st; mode_t mode = 0; security_context_t con; gchar *constr; if (!label_hnd) return NULL; errno = 0; memset(&st, 0, sizeof(st)); rc = g_lstat(dest, &st); if (rc == 0) mode = st.st_mode; else if (errno != ENOENT) return NULL; errno = 0; rc = selabel_lookup_raw(label_hnd, &con, dest, mode); if (rc < 0 && errno != ENOENT) { errno = 0; return NULL; } constr = g_strdup(con); freecon(con); return constr; #endif return NULL; } gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest) { #ifdef HAVE_SYS_MOUNT_H gchar *opts; gchar *context; int result; TRACE (); context = ck_selinux_lookup_context(dest); if (context) { opts = g_strdup_printf ("mode=0700,uid=%d,rootcontext=%s", uid, context); } else { opts = g_strdup_printf ("mode=0700,uid=%d", uid); } g_debug ("mounting tmpfs. uid=%d, gid=%d, dest=%s, opts=%s", uid, gid, dest, opts); result = mount("none", dest, "tmpfs", 0, opts); g_free (context); g_free (opts); if (result == 0) { return TRUE; } else { g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno)); errno = 0; return FALSE; } #endif return FALSE; } gboolean ck_remove_tmpfs (guint uid, const char* dest) { #ifdef HAVE_SYS_MOUNT_H int result; TRACE (); result = umount2(dest, MNT_DETACH); if (result == 0) { return TRUE; } g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno)); errno = 0; #endif return FALSE; } #ifdef HAVE_SYS_VT_SIGNAL /* For the moment this is Linux only. * Returns the vt file descriptor or < 0 on failure. * /sys/class/tty/tty0/active on Linux */ gint ck_get_vt_signal_fd (void) { gint fd; const char *errmsg = NULL; errno = 0; /* Open the magic Linux location */ fd = open ("/sys/class/tty/tty0/active", O_RDONLY); if (fd < 0) { errmsg = g_strerror (errno); g_error ("ck_get_vt_signal_fd: Error opening sys file: %s", errmsg); } return fd; } static gboolean poll_vt_fd (gint sys_fd) { struct pollfd fds[1]; const char *errmsg = NULL; errno = 0; fds[0].fd = sys_fd; fds[0].events = POLLPRI; for(;;) { g_debug ("poll_vt_fd: polling"); if (poll(fds, 1, -1) < 0) { errmsg = g_strerror (errno); /* Error handling */ if (errno == EINTR || errno == EAGAIN) { g_debug ("poll_vt_fd: Interrupted while waiting for vt event: %s", errmsg); /* try again */ } else { g_error ("poll_vt_fd: Error polling for vt event: %s", errmsg); return FALSE; } } else if (fds[0].revents & POLLPRI) { /* There's something we care about! */ return TRUE; } else { /* Something we don't care about */ } } return FALSE; } static gint read_from_vt_fd (gint sys_fd) { gint ret = -1; char new_vt[32]; ssize_t bytes_read = 0; new_vt[31] = '\0'; while (bytes_read == 0) { errno = 0; bytes_read = read (sys_fd, &new_vt, 30); if (bytes_read == -1 && (errno == EAGAIN || errno == EINTR)) { g_debug ("read_from_vt_fd: Interrupted while reading from sys_fd: %s", g_strerror (errno)); bytes_read = 0; /* try again */ } else if (bytes_read == -1) { g_error ("read_from_vt_fd: Error while reading from sys_fd: %s", g_strerror (errno)); ret = -1; } else { gchar unused[32]; gint vty_num; g_debug ("read_from_vt_fd: got %s", new_vt); if(sscanf (new_vt, "%31[a-z-A-Z]%d", unused, &vty_num) == 2) { g_debug ("read_from_vt_fd: parsed as %s %d", unused, vty_num); ret = vty_num; } /* back to the beginning of the fd */ if (lseek(sys_fd, 0,SEEK_SET) < 0) { g_debug ("read_from_vt_fd: error seeking to beginning of file %s", g_strerror (errno)); ret = -1; } } } return ret; } /* * Returns FALSE if something went wrong with reading/polling the * vt fd for VT changes. */ gboolean ck_wait_for_console_switch (gint sys_fd, gint32 *num) { gint new_vt = -1; g_debug ("ck_wait_for_console_switch: sys_fd opened"); /* Poll for changes */ if (poll_vt_fd (sys_fd)) { g_debug ("ck_wait_for_console_switch: poll_vt_fd returned"); /* Read the changes */ new_vt = read_from_vt_fd (sys_fd); if (new_vt >= 0) { g_debug ("ck_wait_for_console_switch: read successful"); /* success, update */ if (num != NULL) { *num = new_vt; } } } return new_vt < 0 ? FALSE : TRUE; } #endif /* HAVE_SYS_VT_SIGNAL */ gboolean ck_sysdeps_init (void) { return ck_selinux_open(); } void ck_sysdeps_fini (void) { ck_selinux_close(); } consolekit2-1.2.6/src/ck-sysdeps-netbsd.c000066400000000000000000000350751446640754400203010ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * Copyright (C) 2007 Joe Marcus Clarke * Copyright (C) 2008 Jared D. McNeill * Copyright (C) 2009 Robert Nagy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #include #define DEV_ENCODE(M,m) ( \ ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ ) #include "ck-sysdeps.h" #ifndef ERROR #define ERROR -1 #endif /* adapted from procps */ struct _CkProcessStat { int pid; int ppid; /* stat,status pid of parent process */ char state; /* stat,status single-char code for process state (S=sleeping) */ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */ unsigned long long utime; /* stat user-mode CPU time accumulated by process */ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */ unsigned long long cutime; /* stat cumulative utime of process and reaped children */ unsigned long long cstime; /* stat cumulative stime of process and reaped children */ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */ unsigned long start_code; /* stat address of beginning of code segment */ unsigned long end_code; /* stat address of end of code segment */ unsigned long start_stack; /* stat address of the bottom of stack for the process */ unsigned long kstk_esp; /* stat kernel stack pointer */ unsigned long kstk_eip; /* stat kernel instruction pointer */ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */ long priority; /* stat kernel scheduling priority */ long nice; /* stat standard unix nice level of process */ long rss; /* stat resident set size from /proc/#/stat (pages) */ long alarm; /* stat ? */ unsigned long rtprio; /* stat real-time priority */ unsigned long sched; /* stat scheduling class */ unsigned long vsize; /* stat number of pages of virtual memory ... */ unsigned long rss_rlim; /* stat resident set size limit? */ unsigned long flags; /* stat kernel flags for the process */ unsigned long min_flt; /* stat number of minor page faults since process start */ unsigned long maj_flt; /* stat number of major page faults since process start */ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */ int pgrp; /* stat process group id */ int session; /* stat session id */ int nlwp; /* stat number of threads, or 0 if no clue */ int tty; /* stat full device number of controlling terminal */ int tpgid; /* stat terminal process group id */ int exit_signal; /* stat might not be SIGCHLD */ int processor; /* stat current (or most recent?) CPU */ uintptr_t penv; /* stat address of initial environment vector */ }; pid_t ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); return stat->ppid; } char * ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup (stat->cmd); } char * ck_process_stat_get_tty (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); if (stat->tty == NODEV){ return NULL; } return g_strdup(devname (stat->tty, S_IFCHR)); } static gboolean get_kinfo_proc2 (pid_t pid, struct kinfo_proc2 *p) { int mib[6]; size_t len; len = sizeof(struct kinfo_proc2); mib[0] = CTL_KERN; mib[1] = KERN_PROC2; mib[2] = KERN_PROC_PID; mib[3] = pid; mib[4] = len; mib[5] = 1; if (sysctl (mib, 6, p, &len, NULL, 0) == -1) { g_warning ("sysctl kern.proc2.pid failed: %s", g_strerror (errno)); return FALSE; } return TRUE; } /* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct kinfo_proc2 p; int num; if (! get_kinfo_proc2 (pid, &p)) { return FALSE; } num = KI_MAXCOMLEN; if (num >= sizeof(P->cmd)) { num = sizeof(P->cmd) - 1; } memcpy (P->cmd, p.p_comm, num); P->cmd[num] = '\0'; P->pid = p.p_pid; P->ppid = p.p_ppid; P->pgrp = p.p__pgid; P->session = p.p_sid; P->rss = p.p_vm_rssize; P->vsize = (unsigned long) p.p_vm_vsize; P->start_time = p.p_ustart_sec; P->wchan = (unsigned long) p.p_wchan; P->state = p.p_stat; P->nice = p.p_nice; P->flags = p.p_realflag; P->tpgid = p.p_tpgid; P->processor = p.p_cpuid; P->nlwp = p.p_nlwps; P->tty = p.p_tdev; if (P->pid != pid) { return FALSE; } return TRUE; } gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error) { gboolean res; CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); if (stat == NULL) { return FALSE; } proc = g_new0 (CkProcessStat, 1); proc->pid = pid; res = stat2proc (pid, proc); if (res) { *stat = proc; } else { *stat = NULL; } return res; } void ck_process_stat_free (CkProcessStat *stat) { g_free (stat); } GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { GHashTable *hash = NULL; char **penv; char errbuf[_POSIX2_LINE_MAX]; kvm_t *kd; struct kinfo_proc2 p; int i; kd = kvm_openfiles (NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (kd == NULL) { g_warning ("kvm_openfiles failed: %s", errbuf); return NULL; } if (! get_kinfo_proc2(pid, &p)) { g_warning ("get_kinfo_proc2 failed: %s", g_strerror (errno)); goto fail; } penv = kvm_getenvv2 (kd, &p, 0); if (penv == NULL) { g_warning ("kvm_getenvv2 failed: %s", g_strerror (errno)); goto fail; } hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (i = 0; penv[i] != NULL; i++) { char **vals; if (!penv[i][0]) continue; vals = g_strsplit (penv[i], "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } fail: kvm_close (kd); return hash; } char * ck_unix_pid_get_env (pid_t pid, const char *var) { GHashTable *hash; char *val = NULL; /* * Would probably be more efficient to just loop through the * environment and return the value, avoiding building the hash * table, but this works for now. */ hash = ck_unix_pid_get_env_hash (pid); if (hash == NULL) return val; val = g_strdup (g_hash_table_lookup (hash, var)); g_hash_table_destroy (hash); return val; } uid_t ck_unix_pid_get_uid (pid_t pid) { uid_t uid; gboolean res; struct kinfo_proc2 p; g_return_val_if_fail (pid > 1, 0); uid = -1; res = get_kinfo_proc2 (pid, &p); if (res) { uid = p.p_uid; } return uid; } gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **idp) { g_return_val_if_fail (pid > 1, FALSE); return FALSE; } gboolean ck_get_max_num_consoles (guint *num) { int max_consoles; int res; gboolean ret; struct ttyent *t; ret = FALSE; max_consoles = 0; res = setttyent (); if (res == 0) { goto done; } while ((t = getttyent ()) != NULL) { if (t->ty_status & TTY_ON && strncmp (t->ty_name, "ttyE", 4) == 0) max_consoles++; } ret = TRUE; endttyent (); done: if (num != NULL) { *num = max_consoles; } return ret; } gboolean ck_supports_activatable_consoles (void) { return TRUE; } char * ck_get_console_device_for_num (guint num) { char *device; /* The device number is always one less than the VT number. */ num--; device = g_strdup_printf ("/dev/ttyE%u", num); return device; } gboolean ck_get_console_num_from_device (const char *device, guint *num) { guint n; gboolean ret; n = 0; ret = FALSE; if (device == NULL) { return FALSE; } if (sscanf (device, "/dev/ttyE%u", &n) == 1) { /* The VT number is always one more than the device number. */ n++; ret = TRUE; } if (num != NULL) { *num = n; } return ret; } gboolean ck_get_active_console_num (int console_fd, guint *num) { gboolean ret; int res; int active; g_assert (console_fd != -1); active = 0; ret = FALSE; res = ioctl (console_fd, VT_GETACTIVE, &active); if (res == ERROR) { perror ("ioctl VT_GETACTIVE"); goto out; } g_debug ("Active VT is: %d (ttyE%d)", active, active - 1); ret = TRUE; out: if (num != NULL) { *num = active; } return ret; } gboolean ck_system_can_suspend (void) { static const char acpi_sleep_mibname[] = "hw.acpi.sleep.states"; static const char acpi_suspend_state[] = "S3"; size_t state_len = 0; int apm_fd = -1; if (sysctlbyname (acpi_sleep_mibname, NULL, &state_len, NULL, 0) == 0) { gchar *sleep_states = g_new (char, state_len + 1); if (sysctlbyname (acpi_sleep_mibname, sleep_states, &state_len, NULL, 0) == 0) { sleep_states[state_len] = 0; if (strstr (sleep_states, acpi_suspend_state) != NULL) { g_free (sleep_states); return TRUE; } } else { g_free (sleep_states); } } if (sysctlbyname ("machdep.xen.suspend", NULL, NULL, NULL, 0) == 0) { return TRUE; } apm_fd = open ("/dev/apmctl", O_RDWR); if(apm_fd == -1) { return FALSE; } close(apm_fd); return TRUE; } gboolean ck_system_can_hibernate (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_system_can_hybrid_sleep (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest) { #ifdef HAVE_SYS_MOUNT_H gchar *opts; int result; TRACE (); opts = g_strdup_printf ("mode=0700,uid=%d", uid); result = mount("tmpfs", dest, 0, opts, strlen(opts)); g_free (opts); if (result == 0) { return TRUE; } else { g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno)); errno = 0; return FALSE; } #endif return FALSE; } gboolean ck_remove_tmpfs (guint uid, const gchar *dest) { #ifdef HAVE_SYS_MOUNT_H int result; TRACE (); result = unmount(dest, 0); if (result == 0) { return TRUE; } g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno)); errno = 0; #endif return FALSE; } gboolean ck_sysdeps_init (void) { return TRUE; } void ck_sysdeps_fini (void) { } consolekit2-1.2.6/src/ck-sysdeps-openbsd.c000066400000000000000000000344501446640754400204500ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * Copyright (C) 2007 Joe Marcus Clarke * Copyright (C) 2008 Jared D. McNeill * Copyright (C) 2009 Robert Nagy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __OpenBSD__ #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #include #define DEV_ENCODE(M,m) ( \ ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ ) #include "ck-sysdeps.h" #ifndef ERROR #define ERROR -1 #endif /* adapted from procps */ struct _CkProcessStat { int pid; int ppid; /* stat,status pid of parent process */ char state; /* stat,status single-char code for process state (S=sleeping) */ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */ unsigned long long utime; /* stat user-mode CPU time accumulated by process */ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */ unsigned long long cutime; /* stat cumulative utime of process and reaped children */ unsigned long long cstime; /* stat cumulative stime of process and reaped children */ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */ unsigned long start_code; /* stat address of beginning of code segment */ unsigned long end_code; /* stat address of end of code segment */ unsigned long start_stack; /* stat address of the bottom of stack for the process */ unsigned long kstk_esp; /* stat kernel stack pointer */ unsigned long kstk_eip; /* stat kernel instruction pointer */ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */ long priority; /* stat kernel scheduling priority */ long nice; /* stat standard unix nice level of process */ long rss; /* stat resident set size from /proc/#/stat (pages) */ long alarm; /* stat ? */ unsigned long rtprio; /* stat real-time priority */ unsigned long sched; /* stat scheduling class */ unsigned long vsize; /* stat number of pages of virtual memory ... */ unsigned long rss_rlim; /* stat resident set size limit? */ unsigned long flags; /* stat kernel flags for the process */ unsigned long min_flt; /* stat number of minor page faults since process start */ unsigned long maj_flt; /* stat number of major page faults since process start */ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */ int pgrp; /* stat process group id */ int session; /* stat session id */ int nlwp; /* stat number of threads, or 0 if no clue */ int tty; /* stat full device number of controlling terminal */ int tpgid; /* stat terminal process group id */ int exit_signal; /* stat might not be SIGCHLD */ int processor; /* stat current (or most recent?) CPU */ uintptr_t penv; /* stat address of initial environment vector */ }; pid_t ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); return stat->ppid; } char * ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup (stat->cmd); } char * ck_process_stat_get_tty (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); if (stat->tty == NODEV){ return NULL; } return g_strdup_printf ("/dev/%s", devname (stat->tty, S_IFCHR)); } static gboolean get_kinfo_proc (pid_t pid, struct kinfo_proc *p) { size_t len; int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), 1 }; #ifndef nitems #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) #endif len = sizeof(*p); if (sysctl(mib, nitems(mib), p, &len, NULL, 0) < 0) return FALSE; return TRUE; } /* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct kinfo_proc p; char *ttname; int num; int tty_maj; int tty_min; if (! get_kinfo_proc (pid, &p)) { return FALSE; } num = KI_MAXCOMLEN; if (num >= sizeof P->cmd) { num = sizeof P->cmd - 1; } memcpy (P->cmd, p.p_comm, num); P->cmd[num] = '\0'; P->pid = p.p_pid; P->ppid = p.p_ppid; P->pgrp = p.p__pgid; P->session = p.p_sid; P->rss = p.p_vm_rssize; P->vsize = p.p_vm_dsize + p.p_vm_dsize + p.p_vm_ssize; /* XXX */ P->start_time = p.p_ustart_sec; P->wchan = (unsigned long) p.p_wchan; P->state = p.p_stat; P->nice = p.p_nice; P->flags = p.p_psflags; P->tpgid = p.p_tpgid; P->processor = p.p_cpuid; P->tty = p.p_tdev; if (P->pid != pid) { return FALSE; } return TRUE; } gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error) { gboolean res; CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); if (stat == NULL) { return FALSE; } proc = g_new0 (CkProcessStat, 1); proc->pid = pid; res = stat2proc (pid, proc); if (res) { *stat = proc; } else { *stat = NULL; } return res; } void ck_process_stat_free (CkProcessStat *stat) { g_free (stat); } GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { GHashTable *hash = NULL; char **penv; char errbuf[_POSIX2_LINE_MAX]; kvm_t *kd; struct kinfo_proc p; int i; kd = kvm_openfiles (NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (kd == NULL) { g_warning ("kvm_openfiles failed: %s", errbuf); return NULL; } if (! get_kinfo_proc (pid, &p)) { g_warning ("get_kinfo_proc failed: %s", g_strerror (errno)); goto fail; } penv = kvm_getenvv (kd, &p, 0); if (penv == NULL) { g_warning ("kvm_getenvv failed: %s", kvm_geterr (kd)); goto fail; } hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (i = 0; penv[i] != NULL; i++) { char **vals; if (!penv[i][0]) continue; vals = g_strsplit (penv[i], "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } fail: kvm_close (kd); return hash; } char * ck_unix_pid_get_env (pid_t pid, const char *var) { GHashTable *hash; char *val = NULL; /* * Would probably be more efficient to just loop through the * environment and return the value, avoiding building the hash * table, but this works for now. */ hash = ck_unix_pid_get_env_hash (pid); if (hash == NULL) return val; val = g_strdup (g_hash_table_lookup (hash, var)); g_hash_table_destroy (hash); return val; } uid_t ck_unix_pid_get_uid (pid_t pid) { uid_t uid; gboolean res; struct kinfo_proc p; g_return_val_if_fail (pid > 1, 0); uid = -1; res = get_kinfo_proc (pid, &p); if (res) { uid = p.p_uid; } return uid; } gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **idp) { g_return_val_if_fail (pid > 1, FALSE); return FALSE; } gboolean ck_get_max_num_consoles (guint *num) { int max_consoles; int res; gboolean ret; struct ttyent *t; ret = FALSE; max_consoles = 0; res = setttyent (); if (res == 0) { goto done; } while ((t = getttyent ()) != NULL) { if (t->ty_status & TTY_ON && strncmp (t->ty_name, "ttyC", 4) == 0) max_consoles++; } ret = TRUE; endttyent (); /* * Increment 2 more: * - ttyC4 is marked as off (X11) * - vt_add_watches() for loop misses the last console * ("< max_consoles"; instead of "<=") */ max_consoles++; max_consoles++; done: if (num != NULL) { *num = max_consoles; } return ret; } gboolean ck_supports_activatable_consoles (void) { return TRUE; } char * ck_get_console_device_for_num (guint num) { char *device; #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || defined(__aarch64__) /* The device number is always one less than the VT number. */ num--; #endif device = g_strdup_printf ("/dev/ttyC%u", num); return device; } gboolean ck_get_console_num_from_device (const char *device, guint *num) { guint n; gboolean ret; n = 0; ret = FALSE; if (device == NULL) { return FALSE; } if (sscanf (device, "/dev/ttyC%u", &n) == 1) { #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || defined(__aarch64__) /* The VT number is always one more than the device number. */ n++; #endif ret = TRUE; } if (num != NULL) { *num = n; } return ret; } gboolean ck_get_active_console_num (int console_fd, guint *num) { gboolean ret; int res; int active; g_assert (console_fd != -1); active = 0; ret = FALSE; #if defined(__i386__) || defined(__amd64__) || defined(__powerpc__) || defined(__aarch64__) res = ioctl (console_fd, VT_GETACTIVE, &active); if (res == ERROR) { perror ("ioctl VT_GETACTIVE"); goto out; } g_debug ("Active VT is: %d (ttyC%d)", active, active - 1); #else res = 0; g_debug ("Active console is: ttyC%d", active); #endif ret = TRUE; out: if (num != NULL) { *num = active; } return ret; } gboolean ck_system_can_suspend (void) { /* needs apmd(8) running */ struct stat st; if (stat("/var/run/apmdev", &st) < 0) { return FALSE; } if (!S_ISSOCK(st.st_mode)) { return FALSE; } return TRUE; } gboolean ck_system_can_hibernate (void) { return ck_system_can_suspend(); } gboolean ck_system_can_hybrid_sleep (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest) { #ifdef HAVE_SYS_MOUNT_H gchar *opts; int result; TRACE (); opts = g_strdup_printf ("mode=0700,uid=%d", uid); result = mount("tmpfs", dest, 0, opts); g_free (opts); if (result == 0) { return TRUE; } else { g_info ("Failed to create tmpfs mount, reason was: %s", strerror(errno)); errno = 0; return FALSE; } #endif return FALSE; } gboolean ck_remove_tmpfs (guint uid, const gchar *dest) { #ifdef HAVE_SYS_MOUNT_H int result; TRACE (); result = unmount(dest, 0); if (result == 0) { return TRUE; } g_info ("Failed to unmount tmpfs mount, reason was: %s", strerror(errno)); errno = 0; #endif return FALSE; } gboolean ck_sysdeps_init (void) { return TRUE; } void ck_sysdeps_fini (void) { } consolekit2-1.2.6/src/ck-sysdeps-solaris.c000066400000000000000000000371631446640754400204760ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_VT_H #include #endif #include #define DEV_ENCODE(M,m) ( \ ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ ) #include #include #define _STRUCTURED_PROC 1 #include #define NO_TTY_VALUE DEV_ENCODE(-1,-1) #include "ck-sysdeps.h" #ifndef ERROR #define ERROR -1 #endif /* adapted from procps */ struct _CkProcessStat { int pid; int ppid; /* stat,status pid of parent process */ char state; /* stat,status single-char code for process state (S=sleeping) */ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */ unsigned long long utime; /* stat user-mode CPU time accumulated by process */ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */ unsigned long long cutime; /* stat cumulative utime of process and reaped children */ unsigned long long cstime; /* stat cumulative stime of process and reaped children */ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */ unsigned long start_code; /* stat address of beginning of code segment */ unsigned long end_code; /* stat address of end of code segment */ unsigned long start_stack; /* stat address of the bottom of stack for the process */ unsigned long kstk_esp; /* stat kernel stack pointer */ unsigned long kstk_eip; /* stat kernel instruction pointer */ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */ long priority; /* stat kernel scheduling priority */ long nice; /* stat standard unix nice level of process */ long rss; /* stat resident set size from /proc/#/stat (pages) */ long alarm; /* stat ? */ unsigned long rtprio; /* stat real-time priority */ unsigned long sched; /* stat scheduling class */ unsigned long vsize; /* stat number of pages of virtual memory ... */ unsigned long rss_rlim; /* stat resident set size limit? */ unsigned long flags; /* stat kernel flags for the process */ unsigned long min_flt; /* stat number of minor page faults since process start */ unsigned long maj_flt; /* stat number of major page faults since process start */ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */ int pgrp; /* stat process group id */ int session; /* stat session id */ int nlwp; /* stat number of threads, or 0 if no clue */ int tty; /* stat full device number of controlling terminal */ int tpgid; /* stat terminal process group id */ int exit_signal; /* stat might not be SIGCHLD */ int processor; /* stat current (or most recent?) CPU */ uintptr_t penv; /* stat address of initial environment vector */ char tty_text[16]; /* stat device name */ }; pid_t ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); return stat->ppid; } char * ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); return g_strdup (stat->cmd); } /* adapted from procps */ char * ck_process_stat_get_tty (CkProcessStat *stat) { guint dev; char *tty; guint dev_maj; guint dev_min; pid_t pid; g_return_val_if_fail (stat != NULL, NULL); return g_strdup (stat->tty_text); } #define VT0_FILE "/dev/vt/0" static int get_system_vt_major () { static ret = -1; struct stat st; int res; if (ret >= 0) return ret; res = stat (VT0_FILE, &st); if (res == 0) { ret = major (st.st_rdev); } return ret; } /* return 1 if it works, or 0 for failure */ static gboolean stat2proc (pid_t pid, CkProcessStat *P) { struct psinfo p; char buf[32]; int num; int fd; int tty_maj; int tty_min; snprintf (buf, sizeof buf, "/proc/%d/psinfo", pid); if ((fd = open (buf, O_RDONLY, 0) ) == -1 ) { return FALSE; } num = read (fd, &p, sizeof p); close (fd); if (num != sizeof p) { return FALSE; } num = PRFNSZ; if (num >= sizeof P->cmd) { num = sizeof P->cmd - 1; } memcpy (P->cmd, p.pr_fname, num); /* p.pr_fname or p.pr_lwp.pr_name */ P->cmd[num] = '\0'; P->pid = p.pr_pid; P->ppid = p.pr_ppid; P->pgrp = p.pr_pgid; P->session = p.pr_sid; P->rss = p.pr_rssize; P->vsize = p.pr_size; P->start_time = p.pr_start.tv_sec; P->wchan = p.pr_lwp.pr_wchan; P->state = p.pr_lwp.pr_sname; P->nice = p.pr_lwp.pr_nice; P->priority = p.pr_lwp.pr_pri; /* or pr_oldpri */ P->penv = p.pr_envp; /* we like it Linux-encoded :-) */ tty_maj = major (p.pr_ttydev); tty_min = minor (p.pr_ttydev); P->tty = DEV_ENCODE (tty_maj,tty_min); snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min); if (tty_maj == get_system_vt_major ()) { snprintf (P->tty_text, sizeof P->tty_text, "/dev/vt/%u", tty_min); } if (P->tty == NO_TTY_VALUE) { memcpy (P->tty_text, " ? ", 8); } if (P->pid != pid) { return FALSE; } return TRUE; } gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error) { char *path; char *contents; gsize length; gboolean res; GError *local_error; CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); if (stat == NULL) { return FALSE; } proc = g_new0 (CkProcessStat, 1); proc->pid = pid; res = stat2proc (pid, proc); if (res) { *stat = proc; } else { g_propagate_error (error, local_error); *stat = NULL; } return res; } void ck_process_stat_free (CkProcessStat *stat) { g_free (stat); } GHashTable * ck_unix_pid_get_env_hash (pid_t pid) { GHashTable *hash; char *cmd; char buf[BUFSIZ]; FILE *fp; int i; hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); cmd = g_strdup_printf ("pargs -e %d", pid); fp = popen (cmd, "r"); g_free (cmd); while (fgets (buf, BUFSIZ, fp) != NULL) { g_strchomp (buf); if (g_str_has_prefix (buf, "envp[")) { char *skip_prefix; skip_prefix = strstr (buf, " "); if (skip_prefix != NULL) { char **vals; vals = g_strsplit (skip_prefix + 1, "=", 2); if (vals != NULL) { g_hash_table_insert (hash, g_strdup (vals[0]), g_strdup (vals[1])); g_strfreev (vals); } } } } out: pclose (fp); return hash; } char * ck_unix_pid_get_env (pid_t pid, const char *var) { GHashTable *hash; char *val; /* * Would probably be more efficient to just loop through the * environment and return the value, avoiding building the hash * table, but this works for now. */ hash = ck_unix_pid_get_env_hash (pid); val = g_strdup (g_hash_table_lookup (hash, var)); g_hash_table_destroy (hash); return val; } uid_t ck_unix_pid_get_uid (pid_t pid) { struct stat st; char *path; int uid; int res; g_return_val_if_fail (pid > 1, 0); uid = -1; path = g_strdup_printf ("/proc/%u", (guint)pid); res = stat (path, &st); g_free (path); if (res == 0) { uid = st.st_uid; } return uid; } pid_t ck_unix_pid_get_ppid (pid_t pid) { int ppid; gboolean res; CkProcessStat *stat; g_return_val_if_fail (pid > 1, 0); ppid = -1; res = ck_process_stat_new_for_unix_pid (pid, &stat, NULL); if (! res) { goto out; } ppid = ck_process_stat_get_ppid (stat); ck_process_stat_free (stat); out: return ppid; } gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **idp) { g_return_val_if_fail (pid > 1, FALSE); return FALSE; } gboolean ck_get_max_num_consoles (guint *num) { GError *error; char *svcprop_stdout; int status; int max_consoles; gboolean res; gboolean ret; ret = FALSE; /* * On Solaris, the default number of VT's is determined by * resources and is stored in the vtdaemon SVC property * options/vtnodecount. If the svcprop command fails, then it can * be safely assumed that VT is not supported on this release of * Solaris. */ error = NULL; svcprop_stdout = NULL; status = 0; res = g_spawn_command_line_sync ("/usr/bin/svcprop -p options/nodecount vtdaemon", &svcprop_stdout, NULL, &status, &error); if (res) { if (error == NULL && svcprop_stdout != NULL) { char *end; end = NULL; errno = 0; max_consoles = strtol (svcprop_stdout, &end, 0); if (end == NULL || end == svcprop_stdout || errno != 0) { max_consoles = 0; } else { ret = TRUE; } } } if (num != NULL) { *num = max_consoles; } g_free (svcprop_stdout); return ret; } gboolean ck_supports_activatable_consoles (void) { char *state = NULL; gboolean vt_enabled; state = smf_get_state ("svc:/system/vtdaemon:default"); if (state && g_str_equal (state, SCF_STATE_STRING_ONLINE)) { vt_enabled = TRUE; } else { vt_enabled = FALSE; } g_free (state); return vt_enabled; } char * ck_get_console_device_for_num (guint num) { char *device; if (num == 1) device = g_strdup_printf ("/dev/console", num); else device = g_strdup_printf ("/dev/vt/%u", num); return device; } gboolean ck_get_console_num_from_device (const char *device, guint *num) { guint n; gboolean ret; n = 0; ret = FALSE; if (device == NULL) { return FALSE; } if (strcmp (device, "/dev/console") == 0) { *num = 1; } else if (sscanf (device, "/dev/vt/%u", &n) == 1) { ret = TRUE; } if (num != NULL) { *num = n; } return ret; } gboolean ck_get_active_console_num (int console_fd, guint *num) { gboolean ret; int res; guint active; #ifdef VT_GETSTATE struct vt_stat stat; g_assert (console_fd != -1); active = 0; ret = FALSE; res = ioctl (console_fd, VT_GETSTATE, &stat); if (res == ERROR) { perror ("ioctl VT_GETSTATE"); goto out; } { int i; g_debug ("Current VT: tty%d", stat.v_active); for (i = 1; i <= 16; i++) { gboolean is_on; is_on = stat.v_state & (1 << i); g_debug ("VT %d:%s", i, is_on ? "on" : "off"); } } active = stat.v_active; ret = TRUE; out: if (num != NULL) { *num = active; } #else /* * If not using VT, not really an active number, but return 1, * which maps to "/dev/console". */ ret = TRUE; *num = 1; #endif return ret; } gboolean ck_system_can_suspend (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_system_can_hibernate (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_system_can_hybrid_sleep (void) { /* TODO: not implemented */ return FALSE; } gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest) { return FALSE; } gboolean ck_remove_tmpfs (guint uid, const gchar *dest) { return FALSE; } gboolean ck_sysdeps_init (void) { return TRUE; } void ck_sysdeps_fini (void) { } consolekit2-1.2.6/src/ck-sysdeps-unix.c000066400000000000000000000360761446640754400200070ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LINUX_KD_H #include #endif #if defined(__NetBSD__) || defined(__OpenBSD__) #include #endif #if defined(__NetBSD__) #include #endif #ifdef HAVE_SYS_VT_H #include #endif #ifdef HAVE_SYS_CONSIO_H #include #endif #ifdef HAVE_GETPEERUCRED #include #endif #ifdef HAVE_KVM_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_SYSCTL_H #include #endif #ifdef HAVE_SYS_USER_H #include #endif #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "ck-sysdeps.h" #ifndef ERROR #define ERROR -1 #endif /* Adapted from dbus-sysdeps-unix.c:_dbus_read_credentials_socket() */ gboolean ck_get_socket_peer_credentials (int socket_fd, pid_t *pid, uid_t *uid, GError **error) { gboolean ret = FALSE; uid_t uid_read = 0; pid_t pid_read = 0; #ifdef SO_PEERCRED #ifndef __OpenBSD__ struct ucred cr; #else struct sockpeercred cr; #endif socklen_t cr_len; pid_read = -1; uid_read = -1; cr_len = sizeof (cr); if (getsockopt (socket_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && cr_len == sizeof (cr)) { pid_read = cr.pid; uid_read = cr.uid; ret = TRUE; } else { g_warning ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", cr_len, (int) sizeof (cr), g_strerror (errno)); } #elif defined(HAVE_GETPEERUCRED) ucred_t *ucred; ucred = NULL; if (getpeerucred (socket_fd, &ucred) == 0) { pid_read = ucred_getpid (ucred); uid_read = ucred_geteuid (ucred); ret = TRUE; } else { g_warning ("Failed to getpeerucred() credentials: %s\n", g_strerror (errno)); } if (ucred != NULL) { ucred_free (ucred); } #elif defined(LOCAL_PEEREID) struct unpcbid cr; socklen_t cr_len; cr_len = sizeof (cr); if (getsockopt (socket_fd, 0, LOCAL_PEEREID, &cr, &cr_len) == 0 && cr_len == sizeof (cr)) { pid_read = cr.unp_pid; uid_read = cr.unp_euid; ret = TRUE; } else { g_warning ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", cr_len, (int) sizeof (cr), g_strerror (errno)); } #elif defined(HAVE_GETPEEREID) gid_t dummy; char errbuf[_POSIX2_LINE_MAX]; int cnt = 0; kvm_t* kd; struct kinfo_proc * prc; if (getpeereid (socket_fd, &uid_read, &dummy) == 0) { ret = TRUE; } else { g_warning ("Failed to getpeereid() credentials: %s\n", g_strerror (errno)); } #if defined(__FreeBSD__) kd = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf); if (kd == NULL) { g_warning ("kvm_openfiles failed: %s", errbuf); return FALSE; } prc = kvm_getprocs (kd, KERN_PROC_UID, uid_read, &cnt); for (int i = 0; i < cnt; i++) { if(strncmp (prc[i].ki_comm, "Xorg", 4) == 0) { pid_read = prc[i].ki_pid; break; } } kvm_close(kd); #endif /* __FreeBSD__ */ #if defined(__DragonFly__) kd = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf); if (kd == NULL) { g_warning ("kvm_openfiles failed: %s", errbuf); return FALSE; } prc = kvm_getprocs (kd, KERN_PROC_UID, uid_read, &cnt); for (int i = 0; i < cnt; i++) { if(strncmp (prc[i].kp_comm, "Xorg", 4) == 0) { pid_read = prc[i].kp_pid; break; } } kvm_close(kd); #endif /* DragonFly */ #else /* !SO_PEERCRED && !HAVE_GETPEERUCRED */ g_warning ("Socket credentials not supported on this OS\n"); #endif if (pid != NULL) { *pid = pid_read; } if (uid != NULL) { *uid = uid_read; } return ret; } /* * getfd.c * * Get an fd for use with kbd/console ioctls. * We try several things because opening /dev/console will fail * if someone else used X (which does a chown on /dev/console). */ gboolean ck_fd_is_a_console (int fd, const gchar *fnam) { #if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) struct vt_stat vts; #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__) int vers; #endif int kb_ok; errno = 0; #if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) kb_ok = (ioctl (fd, VT_GETSTATE, &vts) == 0); #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__) kb_ok = (ioctl (fd, CONS_GETVERS, &vers) == 0); #else kb_ok = 1; #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__DragonFly__) return ((isatty (fd) || g_strcmp0 (fnam, "/dev/consolectl") == 0) && kb_ok); #else return (isatty (fd) && kb_ok); #endif } int ck_open_a_console (char *fnam) { int fd; #ifdef __linux__ again: #endif /* __linux__ */ /* OpenBSD only allows change-setting ioctls when FWRITE is set on the fd */ #ifdef __OpenBSD__ fd = open (fnam, O_WRONLY | O_NOCTTY); #else fd = open (fnam, O_RDONLY | O_NOCTTY); if (fd < 0 && errno == EACCES) fd = open (fnam, O_WRONLY | O_NOCTTY); #endif #ifdef __linux__ if (fd < 0 && errno == EIO) { /* Linux can return EIO if the tty is currently closing, * which can happen if multiple processes are opening and * closing the console in parallel. Unfortunately it can * also return EIO in more serious situations too (see * https://bugs.launchpad.net/bugs/554172), but there isn't * much we can do about that since we really need a console * fd. */ struct timespec ts = { 0, 100000000 }; /* 0.1 seconds */ nanosleep (&ts, NULL); goto again; } #endif /* __linux__ */ if (fd < 0) return -1; if (! ck_fd_is_a_console (fd, fnam)) { close (fd); fd = -1; } return fd; } int ck_get_a_console_fd (void) { int fd; fd = -1; #ifdef __sun /* On Solaris, first try Sun VT device. */ fd = ck_open_a_console ("/dev/vt/active"); if (fd >= 0) { goto done; } fd = ck_open_a_console ("/dev/vt/0"); if (fd >= 0) { goto done; } #endif #if defined(__NetBSD__) fd = ck_open_a_console ("/dev/ttyE0"); if (fd >= 0) { goto done; } #endif #if defined(__OpenBSD__) fd = ck_open_a_console ("/dev/ttyCcfg"); if (fd >= 0) { goto done; } #endif #ifdef _PATH_TTY fd = ck_open_a_console (_PATH_TTY); if (fd >= 0) { goto done; } #endif fd = ck_open_a_console ("/dev/tty"); if (fd >= 0) { goto done; } fd = ck_open_a_console ("/dev/tty0"); if (fd >= 0) { goto done; } #ifdef _PATH_CONSOLE fd = ck_open_a_console (_PATH_CONSOLE); if (fd >= 0) { goto done; } #endif fd = ck_open_a_console ("/dev/console"); if (fd >= 0) { goto done; } for (fd = 0; fd < 3; fd++) { if (ck_fd_is_a_console (fd, "")) { goto done; } } done: return fd; } gboolean ck_is_root_user (void) { #ifndef G_OS_WIN32 uid_t ruid; #ifdef HAVE_GETRESUID uid_t euid, suid; /* Real, effective and saved user ID's */ gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ if (getresuid (&ruid, &euid, &suid) != 0 || getresgid (&rgid, &egid, &sgid) != 0) #endif /* HAVE_GETRESUID */ { ruid = getuid (); } if (ruid == 0) { return TRUE; } #endif return FALSE; } /* Call g_free on string when done using it. [transfer: full] */ static gchar * get_rundir (guint uid) { const gchar *base; TRACE (); base = RUNDIR "/user"; return g_strdup_printf ("%s/%d", base, uid); } static gboolean create_rundir_base (guint uid) { const gchar *base; TRACE (); base = RUNDIR "/user"; /* Create the base directory that we will own. */ if (g_mkdir_with_parents (base, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { g_warning ("Failed to create %s, reason was: %s", base, strerror(errno)); errno = 0; return FALSE; } /* ensure we have ownership */ if (chown (base, 0, 0) != 0) { g_warning ("Failed to chown %s, reason was: %s", base, strerror(errno)); errno = 0; return FALSE; } return TRUE; } static gboolean remove_rundir (guint uid, const gchar *dest) { gchar *command; GError *error = NULL; gboolean res; TRACE (); g_return_val_if_fail (dest, FALSE); if (uid < 1) { g_debug ("We didn't create a runtime dir for root, nothing to remove"); return FALSE; } command = g_strdup_printf (LIBEXECDIR "/ck-remove-directory --uid=%d --dest=%s", uid, dest); res = g_spawn_command_line_sync (command, NULL, NULL, NULL, &error); if (! res) { g_warning ("Unable to remove user runtime dir '%s' error was: %s", dest, error->message); g_clear_error (&error); return FALSE; } return TRUE; } gchar * ck_generate_runtime_dir_for_user (guint uid) { gchar *dest; struct passwd *pwent; TRACE (); errno = 0; pwent = getpwuid (uid); if (pwent == NULL) { g_warning ("Unable to lookup UID: %s", g_strerror (errno)); errno = 0; return NULL; } /* ensure we have created the base directory */ if (create_rundir_base (uid) == FALSE) { return NULL; } dest = get_rundir (uid); /* Ensure any files from the last session are removed */ if (g_file_test (dest, G_FILE_TEST_EXISTS) == TRUE) { remove_rundir (uid, dest); } /* Create the new directory */ if (g_mkdir_with_parents (dest, S_IRWXU) != 0) { g_warning ("Failed to create XDG_RUNTIME_DIR, reason was: %s", strerror(errno)); errno = 0; g_free (dest); return NULL; } g_debug ("setting uid %d, gid %d", uid, pwent->pw_gid); /* assign ownership to the user */ if (chown (dest, uid, pwent->pw_gid) != 0) { g_warning ("Failed to chown XDG_RUNTIME_DIR, reason was: %s", strerror(errno)); errno = 0; g_free (dest); return NULL; } /* attempt to make it a small tmpfs location */ ck_make_tmpfs (uid, pwent->pw_gid, dest); return dest; } gboolean ck_remove_runtime_dir_for_user (guint uid) { gchar *dest; TRACE (); dest = get_rundir (uid); /* attempt to remove the tmpfs */ ck_remove_tmpfs (uid, dest); /* remove the user's runtime dir now that all user sessions * are gone */ remove_rundir (uid, dest); g_free (dest); return TRUE; } gboolean ck_wait_for_active_console_num (int console_fd, guint num) { gboolean ret; int res; g_assert (console_fd != -1); again: ret = FALSE; errno = 0; #ifdef VT_WAITACTIVE g_debug ("VT_WAITACTIVE for vt %d", num); res = ioctl (console_fd, VT_WAITACTIVE, num); g_debug ("VT_WAITACTIVE for vt %d returned %d", num, res); #else res = ERROR; errno = ENOTSUP; #endif if (res == ERROR) { const char *errmsg; errmsg = g_strerror (errno); if (errno == EINTR) { g_debug ("Interrupted waiting for native console %d activation: %s", num, errmsg); goto again; } else if (errno == ENOTSUP) { g_debug ("Console activation not supported on this system"); } else { g_warning ("Error waiting for native console %d activation: %s", num, errmsg); } goto out; } ret = TRUE; out: return ret; } gboolean ck_activate_console_num (int console_fd, guint num) { gboolean ret; int res; g_assert (console_fd != -1); ret = FALSE; errno = 0; #ifdef VT_ACTIVATE res = ioctl (console_fd, VT_ACTIVATE, num); #else res = ERROR; errno = ENOTSUP; #endif if (res == 0) { ret = TRUE; } else { if (errno == ENOTSUP) { g_debug ("Console activation not supported on this system"); } else { g_warning ("Unable to activate console: %s", g_strerror (errno)); } } return ret; } consolekit2-1.2.6/src/ck-sysdeps.h000066400000000000000000000123241446640754400170210ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_SYSDEPS_H #define __CK_SYSDEPS_H #include "config.h" #include G_BEGIN_DECLS typedef struct _CkProcessStat CkProcessStat; gboolean ck_sysdeps_init (void); void ck_sysdeps_fini (void); gboolean ck_process_stat_new_for_unix_pid (pid_t pid, CkProcessStat **stat, GError **error); pid_t ck_process_stat_get_ppid (CkProcessStat *stat); char *ck_process_stat_get_tty (CkProcessStat *stat); char *ck_process_stat_get_cmd (CkProcessStat *stat); void ck_process_stat_free (CkProcessStat *stat); char *ck_unix_pid_get_env (pid_t pid, const char *var); GHashTable *ck_unix_pid_get_env_hash (pid_t pid); pid_t ck_unix_pid_get_ppid (pid_t pid); uid_t ck_unix_pid_get_uid (pid_t pid); gboolean ck_unix_pid_get_login_session_id (pid_t pid, char **id); gboolean ck_get_socket_peer_credentials (int socket_fd, pid_t *pid, uid_t *uid, GError **error); int ck_get_a_console_fd (void); gboolean ck_fd_is_a_console (int fd, const gchar *fnam); int ck_open_a_console (char *fnam); gboolean ck_is_root_user (void); gchar * ck_generate_runtime_dir_for_user (guint uid); gboolean ck_remove_runtime_dir_for_user (guint uid); gboolean ck_make_tmpfs (guint uid, guint gid, const gchar *dest); gboolean ck_remove_tmpfs (guint uid, const gchar *dest); gboolean ck_get_max_num_consoles (guint *num); gboolean ck_supports_activatable_consoles (void); char * ck_get_console_device_for_num (guint num); gboolean ck_get_console_num_from_device (const char *device, guint *num); gboolean ck_get_active_console_num (int console_fd, guint *num); gboolean ck_activate_console_num (int console_fd, guint num); gboolean ck_wait_for_active_console_num (int console_fd, guint num); gboolean ck_system_can_suspend (void); gboolean ck_system_can_hibernate (void); gboolean ck_system_can_hybrid_sleep (void); #ifdef HAVE_SYS_VT_SIGNAL gint ck_get_vt_signal_fd (void); gboolean ck_wait_for_console_switch (gint sys_fd, gint32 *num); #endif /* HAVE_SYS_VT_SIGNAL */ /* compiling with --enable-debug=full enables TRACE messages */ #if defined(CONSOLEKIT_DEBUGGING) #if defined(__NetBSD__) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) #define __DBG_FUNC__ __func__ #elif defined(__GNUC__) && __GNUC__ >= 3 #define __DBG_FUNC__ __FUNCTION__ #elif defined(__SVR4) && defined(__sun) #define __DBG_FUNC__ __func__ #else #define __DBG_FUNC__ "??" #endif #if defined(G_HAVE_ISO_VARARGS) #define TRACE(...) G_STMT_START{ \ g_debug ("TRACE[%s:%d] %s(): entering",__FILE__,__LINE__,__DBG_FUNC__); \ }G_STMT_END #elif defined (G_HAVE_GNUC_VARARGS) #define TRACE(fmt, args...) G_STMT_START{ \ g_debug ("TRACE[%s:%d] %s(): entering",__FILE__,__LINE__,__DBG_FUNC__); \ }G_STMT_END #endif #else /* !defined(CONSOLEKIT_DEBUGGING) */ #define TRACE(...) G_STMT_START{ (void)0; }G_STMT_END #endif G_END_DECLS #endif /* __CK_SYSDEPS_H */ consolekit2-1.2.6/src/ck-tty-idle-monitor.c000066400000000000000000000315561446640754400205520ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "ck-file-monitor.h" #include "ck-tty-idle-monitor.h" #define CK_TTY_IDLE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_TTY_IDLE_MONITOR, CkTtyIdleMonitorPrivate)) #define DEFAULT_THRESHOLD_SECONDS 30 struct CkTtyIdleMonitorPrivate { char *device; guint threshold; guint timeout_id; gboolean idle_hint; GTimeVal idle_since_hint; CkFileMonitor *file_monitor; guint file_notify_id; }; enum { IDLE_HINT_CHANGED, LAST_SIGNAL }; enum { PROP_0, PROP_DEVICE, PROP_THRESHOLD, }; static guint signals [LAST_SIGNAL] = { 0, }; static void ck_tty_idle_monitor_finalize (GObject *object); static void schedule_tty_check (CkTtyIdleMonitor *monitor, guint seconds); G_DEFINE_TYPE (CkTtyIdleMonitor, ck_tty_idle_monitor, G_TYPE_OBJECT) GQuark ck_tty_idle_monitor_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("ck_tty_idle_monitor_error"); } return ret; } static gboolean tty_idle_monitor_set_idle_hint_internal (CkTtyIdleMonitor *tty_idle_monitor, gboolean idle_hint) { if (tty_idle_monitor->priv->idle_hint != idle_hint) { tty_idle_monitor->priv->idle_hint = idle_hint; g_debug ("Emitting idle-changed for tty_idle_monitor %s: %d", tty_idle_monitor->priv->device, idle_hint); g_signal_emit (tty_idle_monitor, signals [IDLE_HINT_CHANGED], 0, idle_hint); return TRUE; } return FALSE; } static void ck_tty_idle_monitor_set_device (CkTtyIdleMonitor *monitor, const char *device) { g_return_if_fail (CK_IS_TTY_IDLE_MONITOR (monitor)); g_free (monitor->priv->device); monitor->priv->device = g_strdup (device); } void ck_tty_idle_monitor_set_threshold (CkTtyIdleMonitor *monitor, guint threshold) { g_return_if_fail (CK_IS_TTY_IDLE_MONITOR (monitor)); monitor->priv->threshold = threshold; } static void ck_tty_idle_monitor_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { CkTtyIdleMonitor *self; self = CK_TTY_IDLE_MONITOR (object); switch (prop_id) { case PROP_DEVICE: ck_tty_idle_monitor_set_device (self, g_value_get_string (value)); break; case PROP_THRESHOLD: ck_tty_idle_monitor_set_threshold (self, g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ck_tty_idle_monitor_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { CkTtyIdleMonitor *self; self = CK_TTY_IDLE_MONITOR (object); switch (prop_id) { case PROP_DEVICE: g_value_set_string (value, self->priv->device); break; case PROP_THRESHOLD: g_value_set_uint (value, self->priv->threshold); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void remove_idle_hint_timeout (CkTtyIdleMonitor *tty_idle_monitor) { g_debug ("remove_idle_hint_timeout: checking timeout_id %d", tty_idle_monitor->priv->timeout_id); if (tty_idle_monitor->priv->timeout_id > 0) { g_source_remove (tty_idle_monitor->priv->timeout_id); tty_idle_monitor->priv->timeout_id = 0; } } static void file_access_cb (CkFileMonitor *file_monitor, CkFileMonitorEvent event, const char *path, CkTtyIdleMonitor *monitor) { g_debug ("File access callback for %s", path); tty_idle_monitor_set_idle_hint_internal (monitor, FALSE); /* this resets timers */ ck_tty_idle_monitor_start (monitor); } static gboolean monitor_add_watch (CkTtyIdleMonitor *monitor) { if (monitor->priv->file_monitor == NULL) { monitor->priv->file_monitor = ck_file_monitor_new (); } if (monitor->priv->file_notify_id != 0) { g_debug ("monitor_add_watch: creating a new file_notify_id when one already exists"); } monitor->priv->file_notify_id = ck_file_monitor_add_notify (monitor->priv->file_monitor, monitor->priv->device, CK_FILE_MONITOR_EVENT_ACCESS, (CkFileMonitorNotifyFunc)file_access_cb, monitor); return monitor->priv->file_notify_id > 0; } static gboolean monitor_remove_watch (CkTtyIdleMonitor *monitor) { if (monitor->priv->file_monitor != NULL && monitor->priv->file_notify_id > 0) { g_debug ("Removing notify"); ck_file_monitor_remove_notify (monitor->priv->file_monitor, monitor->priv->file_notify_id); } return FALSE; } static gboolean check_tty_idle (CkTtyIdleMonitor *monitor) { struct stat sb; gboolean is_idle; time_t now; time_t idletime; time_t last_access; g_debug ("check_tty_idle: setting timeout_id %d to 0", monitor->priv->timeout_id); monitor->priv->timeout_id = 0; if (monitor->priv->device == NULL) { return FALSE; } if (g_stat (monitor->priv->device, &sb) < 0) { g_debug ("Unable to stat: %s: %s", monitor->priv->device, g_strerror (errno)); return FALSE; } last_access = sb.st_atime; time (&now); if (last_access > now) { last_access = now; } idletime = now - last_access; is_idle = (idletime >= monitor->priv->threshold); tty_idle_monitor_set_idle_hint_internal (monitor, is_idle); if (is_idle) { if (! monitor_add_watch (monitor)) { /* if we can't add a watch just add a new timer */ g_debug ("Couldn't add watch: rescheduling check for %u sec", monitor->priv->threshold); schedule_tty_check (monitor, monitor->priv->threshold); } } else { guint remaining; remaining = monitor->priv->threshold - idletime; if (remaining > 0) { g_debug ("Time left, rescheduling check for %u sec", remaining); /* reschedule for time left */ schedule_tty_check (monitor, remaining); } else { g_debug ("restarting check for %u sec", monitor->priv->threshold); schedule_tty_check (monitor, monitor->priv->threshold); } } return FALSE; } static void schedule_tty_check (CkTtyIdleMonitor *monitor, guint seconds) { g_debug ("schedule_tty_check: timeout_id %d", monitor->priv->timeout_id); if (monitor->priv->timeout_id == 0) { #if GLIB_CHECK_VERSION(2,14,0) monitor->priv->timeout_id = g_timeout_add_seconds (seconds, (GSourceFunc)check_tty_idle, monitor); #else monitor->priv->timeout_id = g_timeout_add (seconds * 1000, (GSourceFunc)check_tty_idle, monitor); #endif g_debug ("schedule_tty_check: timeout_id %d", monitor->priv->timeout_id); } } static void add_idle_hint_timeout (CkTtyIdleMonitor *monitor) { schedule_tty_check (monitor, monitor->priv->threshold); } void ck_tty_idle_monitor_stop (CkTtyIdleMonitor *monitor) { remove_idle_hint_timeout (monitor); monitor_remove_watch (monitor); } void ck_tty_idle_monitor_start (CkTtyIdleMonitor *monitor) { ck_tty_idle_monitor_stop (monitor); add_idle_hint_timeout (monitor); } static void ck_tty_idle_monitor_class_init (CkTtyIdleMonitorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->get_property = ck_tty_idle_monitor_get_property; object_class->set_property = ck_tty_idle_monitor_set_property; object_class->finalize = ck_tty_idle_monitor_finalize; signals [IDLE_HINT_CHANGED] = g_signal_new ("idle-hint-changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkTtyIdleMonitorClass, idle_hint_changed), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); g_object_class_install_property (object_class, PROP_DEVICE, g_param_spec_string ("device", "device", "device", NULL, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_THRESHOLD, g_param_spec_uint ("threshold", "Threshold", "Threshold", 0, G_MAXINT, DEFAULT_THRESHOLD_SECONDS, G_PARAM_READWRITE)); g_type_class_add_private (klass, sizeof (CkTtyIdleMonitorPrivate)); } static void ck_tty_idle_monitor_init (CkTtyIdleMonitor *monitor) { monitor->priv = CK_TTY_IDLE_MONITOR_GET_PRIVATE (monitor); monitor->priv->threshold = DEFAULT_THRESHOLD_SECONDS; } static void ck_tty_idle_monitor_finalize (GObject *object) { CkTtyIdleMonitor *monitor; g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_TTY_IDLE_MONITOR (object)); monitor = CK_TTY_IDLE_MONITOR (object); g_return_if_fail (monitor->priv != NULL); ck_tty_idle_monitor_stop (monitor); g_free (monitor->priv->device); G_OBJECT_CLASS (ck_tty_idle_monitor_parent_class)->finalize (object); } CkTtyIdleMonitor * ck_tty_idle_monitor_new (const char *device) { GObject *object; object = g_object_new (CK_TYPE_TTY_IDLE_MONITOR, "device", device, NULL); return CK_TTY_IDLE_MONITOR (object); } consolekit2-1.2.6/src/ck-tty-idle-monitor.h000066400000000000000000000054051446640754400205510ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_TTY_IDLE_MONITOR_H #define __CK_TTY_IDLE_MONITOR_H #include G_BEGIN_DECLS #define CK_TYPE_TTY_IDLE_MONITOR (ck_tty_idle_monitor_get_type ()) #define CK_TTY_IDLE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_TTY_IDLE_MONITOR, CkTtyIdleMonitor)) #define CK_TTY_IDLE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_TTY_IDLE_MONITOR, CkTtyIdleMonitorClass)) #define CK_IS_TTY_IDLE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_TTY_IDLE_MONITOR)) #define CK_IS_TTY_IDLE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_TTY_IDLE_MONITOR)) #define CK_TTY_IDLE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_TTY_IDLE_MONITOR, CkTtyIdleMonitorClass)) typedef struct CkTtyIdleMonitorPrivate CkTtyIdleMonitorPrivate; typedef struct { GObject parent; CkTtyIdleMonitorPrivate *priv; } CkTtyIdleMonitor; typedef struct { GObjectClass parent_class; void (* idle_hint_changed) (CkTtyIdleMonitor *monitor, gboolean idle_hint); } CkTtyIdleMonitorClass; typedef enum { CK_TTY_IDLE_MONITOR_ERROR_GENERAL } CkTtyIdleMonitorError; #define CK_TTY_IDLE_MONITOR_ERROR ck_tty_idle_monitor_error_quark () GQuark ck_tty_idle_monitor_error_quark (void); GType ck_tty_idle_monitor_get_type (void); CkTtyIdleMonitor * ck_tty_idle_monitor_new (const char *device); void ck_tty_idle_monitor_set_threshold (CkTtyIdleMonitor *monitor, guint seconds); void ck_tty_idle_monitor_start (CkTtyIdleMonitor *monitor); void ck_tty_idle_monitor_stop (CkTtyIdleMonitor *monitor); G_END_DECLS #endif /* __CK_TTY_IDLE_MONITOR_H */ consolekit2-1.2.6/src/ck-vt-monitor.c000066400000000000000000000375171446640754400174530ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006-2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "ck-vt-monitor.h" #include "ck-sysdeps.h" #include "ck-marshal.h" #if defined (__sun) && defined (HAVE_SYS_VT_H) #include #include #include #endif #ifndef ERROR #define ERROR -1 #endif #define CK_VT_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_VT_MONITOR, CkVtMonitorPrivate)) struct CkVtMonitorPrivate { int vfd; GHashTable *vt_thread_hash; guint active_num; GAsyncQueue *event_queue; guint process_queue_id; }; enum { ACTIVE_CHANGED, LAST_SIGNAL }; enum { PROP_0, }; static guint signals [LAST_SIGNAL] = { 0, }; static void ck_vt_monitor_finalize (GObject *object); static void vt_add_watches (CkVtMonitor *vt_monitor); G_DEFINE_TYPE (CkVtMonitor, ck_vt_monitor, G_TYPE_OBJECT) G_LOCK_DEFINE_STATIC (hash_lock); G_LOCK_DEFINE_STATIC (schedule_lock); static gpointer vt_object = NULL; GQuark ck_vt_monitor_error_quark (void) { static GQuark ret = 0; if (ret == 0) { ret = g_quark_from_static_string ("ck_vt_monitor_error"); } return ret; } gboolean ck_vt_monitor_set_active (CkVtMonitor *vt_monitor, guint32 num, GError **error) { gboolean ret; int res; g_return_val_if_fail (CK_IS_VT_MONITOR (vt_monitor), FALSE); if (num == vt_monitor->priv->active_num) { g_set_error (error, CK_VT_MONITOR_ERROR, CK_VT_MONITOR_ERROR_ALREADY_ACTIVE, _("Session is already active")); return FALSE; } if (vt_monitor->priv->vfd == ERROR) { g_set_error (error, CK_VT_MONITOR_ERROR, CK_VT_MONITOR_ERROR_NO_CONSOLE, _("No consoles available")); return FALSE; } res = ck_activate_console_num (vt_monitor->priv->vfd, num); if (res) { ret = TRUE; } else { g_set_error (error, CK_VT_MONITOR_ERROR, CK_VT_MONITOR_ERROR_GENERAL, _("Unable to activate session")); ret = FALSE; } return ret; } gboolean ck_vt_monitor_get_active (CkVtMonitor *vt_monitor, guint32 *num, GError **error) { if (num != NULL) { *num = 0; } g_return_val_if_fail (CK_IS_VT_MONITOR (vt_monitor), FALSE); if (vt_monitor->priv->vfd == ERROR) { g_set_error (error, CK_VT_MONITOR_ERROR, CK_VT_MONITOR_ERROR_NO_CONSOLE, _("No consoles available")); return FALSE; } if (num != NULL) { *num = vt_monitor->priv->active_num; } return TRUE; } #if defined (__sun) && defined (HAVE_SYS_VT_H) static void handle_vt_active (void) { struct vt_stat state; guint num; CkVtMonitor *vt_monitor = CK_VT_MONITOR (vt_object); g_return_if_fail (CK_IS_VT_MONITOR (vt_monitor)); /* * state.v_active value: [1 .. N] * * VT device file VT # * * /dev/console --- VT #1 * /dev/vt/2 --- VT #2 * /dev/vt/3 --- VT #3 * /dev/vt/N --- VT #4 */ if (ioctl (vt_monitor->priv->vfd, VT_GETSTATE, &state) != -1) { num = state.v_active; } else { g_debug ("Fails to ioctl VT_GETSTATE"); } if (vt_monitor->priv->active_num != num) { g_debug ("Changing active VT: %d", num); vt_monitor->priv->active_num = num; g_signal_emit (vt_monitor, signals [ACTIVE_CHANGED], 0, num); } else { g_debug ("VT activated but already active: %d", num); } } #endif static void change_active_num (CkVtMonitor *vt_monitor, guint num) { if (vt_monitor->priv->active_num != num) { g_debug ("Changing active VT: %d", num); vt_monitor->priv->active_num = num; /* add a watch to every vt without a thread */ vt_add_watches (vt_monitor); g_signal_emit (vt_monitor, signals[ACTIVE_CHANGED], 0, num); } else { g_debug ("VT activated but already active: %d", num); } } typedef struct { gint32 num; CkVtMonitor *vt_monitor; } ThreadData; typedef struct { gint32 num; } EventData; static void thread_data_free (ThreadData *data) { if (data == NULL) { return; } g_free (data); } static void event_data_free (EventData *data) { if (data == NULL) { return; } g_free (data); } static gboolean process_queue (CkVtMonitor *vt_monitor) { int i; int queue_length; EventData *data; EventData *d; g_async_queue_lock (vt_monitor->priv->event_queue); g_debug ("Processing VT event queue"); queue_length = g_async_queue_length_unlocked (vt_monitor->priv->event_queue); data = NULL; G_LOCK (hash_lock); /* compress events in the queue */ for (i = 0; i < queue_length; i++) { d = g_async_queue_try_pop_unlocked (vt_monitor->priv->event_queue); if (d == NULL) { continue; } if (data != NULL) { g_debug ("Compressing queue; skipping event for VT %d", data->num); event_data_free (data); } data = d; } G_UNLOCK (hash_lock); if (data != NULL) { change_active_num (vt_monitor, data->num); event_data_free (data); } G_LOCK (schedule_lock); vt_monitor->priv->process_queue_id = 0; G_UNLOCK (schedule_lock); g_async_queue_unlock (vt_monitor->priv->event_queue); return FALSE; } static void schedule_process_queue (CkVtMonitor *vt_monitor) { G_LOCK (schedule_lock); if (vt_monitor->priv->process_queue_id == 0) { vt_monitor->priv->process_queue_id = g_idle_add ((GSourceFunc)process_queue, vt_monitor); } G_UNLOCK (schedule_lock); } static void * vt_thread_start (ThreadData *data) { CkVtMonitor *vt_monitor; gboolean res; gint32 num; #ifdef HAVE_SYS_VT_SIGNAL /* Get our FD */ gint sys_fd = ck_get_vt_signal_fd (); #endif vt_monitor = data->vt_monitor; num = data->num; #ifdef HAVE_SYS_VT_SIGNAL while (sys_fd >= 0) { res = ck_wait_for_console_switch (sys_fd, &num); if (! res) { break; } else { EventData *event; /* add event to queue */ event = g_new0 (EventData, 1); event->num = num; g_debug ("Pushing activation event for VT %d onto queue", num); g_async_queue_push (vt_monitor->priv->event_queue, event); /* schedule processing of queue */ schedule_process_queue (vt_monitor); } } if (sys_fd >= 0) close (sys_fd); #else res = ck_wait_for_active_console_num (vt_monitor->priv->vfd, num); if (! res) { /* FIXME: what do we do if it fails? */ } else { EventData *event; /* add event to queue */ event = g_new0 (EventData, 1); event->num = num; g_debug ("Pushing activation event for VT %d onto queue", num); g_async_queue_push (vt_monitor->priv->event_queue, event); /* schedule processing of queue */ schedule_process_queue (vt_monitor); } #endif G_LOCK (hash_lock); if (vt_monitor->priv->vt_thread_hash != NULL) { g_hash_table_remove (vt_monitor->priv->vt_thread_hash, GUINT_TO_POINTER (num)); } G_UNLOCK (hash_lock); thread_data_free (data); g_thread_exit (NULL); return NULL; } static void vt_add_watch_unlocked (CkVtMonitor *vt_monitor, gint32 num) { GThread *thread; GError *error; ThreadData *data; gpointer id; data = g_new0 (ThreadData, 1); data->num = num; data->vt_monitor = vt_monitor; g_debug ("Creating thread for vt %d", num); id = GINT_TO_POINTER (num); error = NULL; #if GLIB_CHECK_VERSION(2, 32, 0) thread = g_thread_try_new ("vt_thread_start", (GThreadFunc)vt_thread_start, data, &error); #else thread = g_thread_create_full ((GThreadFunc)vt_thread_start, data, 65536, FALSE, TRUE, G_THREAD_PRIORITY_NORMAL, &error); #endif if (thread == NULL) { g_debug ("Unable to create thread: %s", error->message); g_error_free (error); } else { g_hash_table_insert (vt_monitor->priv->vt_thread_hash, id, thread); } } static void vt_add_watches (CkVtMonitor *vt_monitor) { #if defined (__sun) && !defined (HAVE_SYS_VT_H) || (defined(__OpenBSD__) && (!defined(__i386__) && !defined(__amd64__) && !defined(__powerpc__) && !defined(__aarch64__))) /* Best to do nothing if VT is not supported */ #elif defined (__sun) && defined (HAVE_SYS_VT_H) /* * Solaris supports synchronous event notification in STREAMS. * Applications that open the virtual console device can * get a asynchronous notification of VT switching by setting * the S_MSG flag in an I_SETSIG STREAMS ioctl. Such processes * receive a SIGPOLL signal when a VT switching succeeds. */ struct sigaction act; act.sa_handler = handle_vt_active; sigemptyset (&act.sa_mask); act.sa_flags = 0; sigaction (SIGPOLL, &act, NULL); ioctl (vt_monitor->priv->vfd, I_SETSIG, S_MSG); #elif defined (HAVE_SYS_VT_SIGNAL) /* We have a method to poll for vt changes, use it */ gpointer id; G_LOCK (hash_lock); id = GINT_TO_POINTER (1); if (g_hash_table_lookup (vt_monitor->priv->vt_thread_hash, id) == NULL) vt_add_watch_unlocked (vt_monitor, 1); G_UNLOCK (hash_lock); #else guint max_consoles; int i; gint32 current_num; G_LOCK (hash_lock); current_num = vt_monitor->priv->active_num; max_consoles = 1; if (! ck_get_max_num_consoles (&max_consoles)) { /* FIXME: this can fail on solaris and freebsd */ } for (i = 1; (guint)i < max_consoles; i++) { gpointer id; /* don't wait on the active vc */ if (i == current_num) { continue; } id = GINT_TO_POINTER (i); /* add a watch to all other VTs that don't have threads */ if (g_hash_table_lookup (vt_monitor->priv->vt_thread_hash, id) == NULL) { vt_add_watch_unlocked (vt_monitor, i); } } G_UNLOCK (hash_lock); #endif } static void ck_vt_monitor_class_init (CkVtMonitorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = ck_vt_monitor_finalize; signals [ACTIVE_CHANGED] = g_signal_new ("active-changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CkVtMonitorClass, active_changed), NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); g_type_class_add_private (klass, sizeof (CkVtMonitorPrivate)); } static void ck_vt_monitor_init (CkVtMonitor *vt_monitor) { int fd; vt_monitor->priv = CK_VT_MONITOR_GET_PRIVATE (vt_monitor); fd = ck_get_a_console_fd (); vt_monitor->priv->vfd = fd; if (fd == ERROR) { const char *errmsg; errmsg = g_strerror (errno); g_warning ("Unable to open a console: %s", errmsg); } else { gboolean res; guint active; res = ck_get_active_console_num (fd, &active); if (! res) { /* FIXME: handle failure */ g_warning ("Could not determine active console"); active = 0; } vt_monitor->priv->active_num = active; vt_monitor->priv->event_queue = g_async_queue_new (); vt_monitor->priv->vt_thread_hash = g_hash_table_new (g_direct_hash, g_direct_equal); vt_add_watches (vt_monitor); } } static void ck_vt_monitor_finalize (GObject *object) { CkVtMonitor *vt_monitor; TRACE (); g_return_if_fail (object != NULL); g_return_if_fail (CK_IS_VT_MONITOR (object)); vt_monitor = CK_VT_MONITOR (object); g_return_if_fail (vt_monitor->priv != NULL); if (vt_monitor->priv->process_queue_id > 0) { g_source_remove (vt_monitor->priv->process_queue_id); vt_monitor->priv->process_queue_id = 0; } if (vt_monitor->priv->event_queue != NULL) { g_async_queue_unref (vt_monitor->priv->event_queue); } if (vt_monitor->priv->vt_thread_hash != NULL) { g_hash_table_destroy (vt_monitor->priv->vt_thread_hash); } if (vt_monitor->priv->vfd != ERROR) { close (vt_monitor->priv->vfd); } G_OBJECT_CLASS (ck_vt_monitor_parent_class)->finalize (object); } CkVtMonitor * ck_vt_monitor_new (void) { if (vt_object != NULL) { g_object_ref (vt_object); } else { vt_object = g_object_new (CK_TYPE_VT_MONITOR, NULL); g_object_add_weak_pointer (vt_object, (gpointer *) &vt_object); } return CK_VT_MONITOR (vt_object); } consolekit2-1.2.6/src/ck-vt-monitor.h000066400000000000000000000053651446640754400174540ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __CK_VT_MONITOR_H #define __CK_VT_MONITOR_H #include G_BEGIN_DECLS #define CK_TYPE_VT_MONITOR (ck_vt_monitor_get_type ()) #define CK_VT_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_VT_MONITOR, CkVtMonitor)) #define CK_VT_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_VT_MONITOR, CkVtMonitorClass)) #define CK_IS_VT_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_VT_MONITOR)) #define CK_IS_VT_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_VT_MONITOR)) #define CK_VT_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_VT_MONITOR, CkVtMonitorClass)) typedef struct CkVtMonitorPrivate CkVtMonitorPrivate; typedef struct { GObject parent; CkVtMonitorPrivate *priv; } CkVtMonitor; typedef struct { GObjectClass parent_class; void (* active_changed) (CkVtMonitor *vt_monitor, guint num); } CkVtMonitorClass; typedef enum { CK_VT_MONITOR_ERROR_GENERAL, CK_VT_MONITOR_ERROR_ALREADY_ACTIVE, CK_VT_MONITOR_ERROR_NO_CONSOLE } CkVtMonitorError; #define CK_VT_MONITOR_ERROR ck_vt_monitor_error_quark () GQuark ck_vt_monitor_error_quark (void); GType ck_vt_monitor_get_type (void); CkVtMonitor * ck_vt_monitor_new (void); gboolean ck_vt_monitor_set_active (CkVtMonitor *vt_monitor, guint32 num, GError **error); gboolean ck_vt_monitor_get_active (CkVtMonitor *vt_monitor, guint32 *num, GError **error); G_END_DECLS #endif /* __CK_VT_MONITOR_H */ consolekit2-1.2.6/src/main.c000066400000000000000000000177501446640754400156630ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006-2007 William Jon McCann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-sysdeps.h" #include "ck-manager.h" #include "ck-log.h" #define CK_DBUS_NAME "org.freedesktop.ConsoleKit" static GMainLoop *loop = NULL; static gboolean timed_exit_cb (GMainLoop *l) { g_main_loop_quit (l); return FALSE; } static void bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { CkManager *manager; g_debug ("bus_acquired %s\n", name); ck_sysdeps_init(); manager = ck_manager_new (connection); if (manager == NULL) { g_critical ("Could not create CkManager"); } } static void name_acquired (GDBusConnection *connection, const gchar *name, gpointer user_data) { g_debug ("name_acquired\n"); } static void name_lost (GDBusConnection *connection, const gchar *name, gpointer user_data) { g_debug ("name_lost\n"); ck_sysdeps_fini(); /* Release the object */ g_debug ("Disconnected from D-Bus"); g_main_loop_quit (loop); } static void delete_pid (void) { unlink (CONSOLE_KIT_PID_FILE); } static void cleanup (void) { delete_pid (); } /* copied from nautilus */ static int debug_log_pipes[2]; static gboolean debug_log_io_cb (GIOChannel *io, GIOCondition condition, gpointer data) { char a; while (read (debug_log_pipes[0], &a, 1) != 1) ; ck_log_toggle_debug (); return TRUE; } static void sigusr1_handler (int sig) { while (write (debug_log_pipes[1], "a", 1) != 1) ; } static void setup_termination_signals (void) { struct sigaction sa; sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (SIGTERM, &sa, NULL); sigaction (SIGQUIT, &sa, NULL); sigaction (SIGINT, &sa, NULL); sigaction (SIGHUP, &sa, NULL); } static void setup_debug_log_signals (void) { struct sigaction sa; GIOChannel *io; if (pipe (debug_log_pipes) == -1) { g_error ("Could not create pipe() for debug log"); } io = g_io_channel_unix_new (debug_log_pipes[0]); g_io_add_watch (io, G_IO_IN, debug_log_io_cb, NULL); sa.sa_handler = sigusr1_handler; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (SIGUSR1, &sa, NULL); } static void setup_debug_log (gboolean debug) { ck_log_init (); ck_log_set_debug (debug); setup_debug_log_signals (); } static void create_pid_file (void) { char *dirname; int res; int pf; ssize_t written; char pid[9]; /* remove old pid file */ unlink (CONSOLE_KIT_PID_FILE); dirname = g_path_get_dirname (CONSOLE_KIT_PID_FILE); errno = 0; res = g_mkdir_with_parents (dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (res < 0) { g_warning ("Unable to create directory %s (%s)", dirname, g_strerror (errno)); } g_free (dirname); /* make a new pid file */ if ((pf = open (CONSOLE_KIT_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) >= 0) { snprintf (pid, sizeof (pid), "%lu\n", (long unsigned) getpid ()); written = write (pf, pid, strlen (pid)); if (written < 1 || (size_t)written != strlen(pid)) { g_warning ("unable to write pid file %s: %s", CONSOLE_KIT_PID_FILE, g_strerror (errno)); } atexit (cleanup); close (pf); } else { g_warning ("Unable to write pid file %s: %s", CONSOLE_KIT_PID_FILE, g_strerror (errno)); } } int main (int argc, char **argv) { GOptionContext *context; GError *error; int ret; gboolean res; guint id; static gboolean debug = FALSE; static gboolean no_daemon = FALSE; static gboolean do_timed_exit = FALSE; static GOptionEntry entries [] = { { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL }, { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &no_daemon, N_("Don't become a daemon"), NULL }, { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time - for debugging"), NULL }, { NULL } }; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif ret = 1; #if !GLIB_CHECK_VERSION(2, 32, 0) if (! g_thread_supported ()) { g_thread_init (NULL); } #endif #if !GLIB_CHECK_VERSION(2, 36, 0) g_type_init (); #endif if (! ck_is_root_user ()) { g_warning (_("You must be root to run this program")); exit (1); } context = g_option_context_new (_("Console kit daemon")); g_option_context_add_main_entries (context, entries, NULL); error = NULL; res = g_option_context_parse (context, &argc, &argv, &error); g_option_context_free (context); if (! res) { g_warning ("%s", error->message); g_clear_error (&error); goto out; } #ifdef CONSOLEKIT_DEBUGGING /* compiling with --enable-debug=full turns debugging on */ debug = TRUE; #endif if (debug) { g_setenv ("G_DEBUG", "fatal_criticals", FALSE); g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); } if (! no_daemon && daemon (0, 0)) { g_error ("Could not daemonize: %s", g_strerror (errno)); g_clear_error (&error); } setup_debug_log (debug); setup_termination_signals (); g_debug ("initializing console-kit-daemon %s", VERSION); id = g_bus_own_name (G_BUS_TYPE_SYSTEM, CK_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, bus_acquired, name_acquired, name_lost, NULL, NULL); create_pid_file (); loop = g_main_loop_new (NULL, FALSE); if (do_timed_exit) { g_timeout_add (1000 * 30, (GSourceFunc) timed_exit_cb, loop); } g_main_loop_run (loop); g_bus_unown_name (id); g_main_loop_unref (loop); ret = 0; out: return ret; } consolekit2-1.2.6/src/mock-ck-collect-session-info.c000066400000000000000000000027051446640754400223120ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2015 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include int main (int argc, char *argv[]) { /* This is a mock for the tools/ck-collect-session-info program. * It provides similar output to the real tool for test-session-leader. * You do not need to run this as root, but as it does nothing there's * little to worry about */ printf ("unix-user = 9000\n"); printf ("x11-display = :0.0\n"); printf ("x11-display-device = /dev/tty15\n"); printf ("display-device = /dev/pts/0\n"); printf ("login-session-id = 99\n"); printf ("is-local = TRUE"); return 0; } consolekit2-1.2.6/src/org.freedesktop.ConsoleKit.Manager.xml000066400000000000000000001141071446640754400240320ustar00rootroot00000000000000 This method initiates a request to restart (ie. reboot) the computer system. May fail with: CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_BUSY This method returns whether the user is authorized to restart the computer system. May fail with: CK_MANAGER_ERROR_FAILED if polkit is used and fails checking authorization. This method initiates a request to stop (ie. shutdown) the computer system. May fail with: CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_BUSY This method returns whether the user is authorized to shutdown the computer system. May fail with: CK_MANAGER_ERROR_FAILED if polkit is used and fails checking authorization. policykit_interactivity determines whether PolicyKit (if enabled) should interactively ask the user for authentication credentials if it needs to. This method emulates the logind implementation. This method initiates a request to reboot the computer system. May fail with: CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_BUSY Since 0.9.2 This method emulates the logind implementation. Returns whether the system supports rebooting and whether the calling user is eligible to reboot the system. Returns one of "na", "yes", "no" or "challenge". If "na" is returned rebooting is not available because of hardware support. If "yes" is returned rebooting is supported and the user may suspend without further authentication. If "no" is returned rebooting is available but the user is not allowed to reboot. If "challenge" is returned rebooting is available, but only after authorization. May fail with: CK_MANAGER_ERROR_FAILED if polkit is used and fails checking authorization. Since 0.9.2 policykit_interactivity determines whether PolicyKit (if enabled) should interactively ask the user for authentication credentials if it needs to. This method initiates a request to shutdown the computer system. May fail with: CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_BUSY Since 0.9.2 This method emulates the logind implementation. Returns whether the system supports shutdown and whether the calling user is eligible to shutdown the system. Returns one of "na", "yes", "no" or "challenge". If "na" is returned shutdown is not available because of hardware support. If "yes" is returned shutdown is supported and the user may hibernate without further authentication. If "no" is returned shutdown is available but the user is not allowed to shutdown. If "challenge" is returned shutdown is available, but only after authorization. May fail with: CK_MANAGER_ERROR_FAILED if polkit is used and fails checking authorization. Since 0.9.2 policykit_interactivity determines whether PolicyKit (if enabled) should interactively ask the user for authentication credentials if it needs to. This method initiates a request to suspend the computer system. May fail with: CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_BUSY Since 0.9.2 This method emulates the logind implementation. Returns whether the system supports suspending and whether the calling user is eligible to hibernate the system. Returns one of "na", "yes", "no" or "challenge". If "na" is returned suspending is not available because of hardware support. If "yes" is returned suspending is supported and the user may suspend without further authentication. If "no" is returned suspending is available but the user is not allowed to suspend. If "challenge" is returned suspending is available, but only after authorization. May fail with: CK_MANAGER_ERROR_FAILED if polkit is used and fails checking authorization. Since 0.9.1 policykit_interactivity determines whether PolicyKit (if enabled) should interactively ask the user for authentication credentials if it needs to. This method initiates a request to hibernate the computer system. May fail with: CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_BUSY Since 0.9.2 This method emulates the logind implementation. Returns whether the system supports hibernation and whether the calling user is eligible to hibernate the system. Returns one of "na", "yes", "no" or "challenge". If "na" is returned hibernation is not available because of hardware support. If "yes" is returned hibernation is supported and the user may hibernate without further authentication. If "no" is returned hibernation is available but the user is not allowed to hibernate. If "challenge" is returned hibernation is available, but only after authorization. May fail with: CK_MANAGER_ERROR_FAILED if polkit is used and fails checking authorization. Since 0.9.1 policykit_interactivity determines whether PolicyKit (if enabled) should interactively ask the user for authentication credentials if it needs to. This method initiates a request to hybrid sleep (suspend + hibernate) the computer system. May fail with: CK_MANAGER_ERROR_INHIBITED, CK_MANAGER_ERROR_INSUFFICIENT_PERMISSION, CK_MANAGER_ERROR_AUTHORIZATION_REQUIRED, CK_MANAGER_ERROR_GENERAL, CK_MANAGER_ERROR_BUSY Since 0.9.2 This method emulates the logind implementation. Returns whether the system supports hybrid sleep (suspend + hibernate) and whether the calling user is eligible to hybrid sleep the system. Returns one of "na", "yes", "no" or "challenge". If "na" is returned hybrid sleeping is not available because of hardware support. If "yes" is returned hybrid sleeping is supported and the user may hybrid sleep without further authentication. If "no" is returned hybrid sleeping is available but the user is not allowed to hybrid sleep. If "challenge" is returned hybrid sleeping is available, but only after authorization. May fail with: CK_MANAGER_ERROR_FAILED if polkit is used and fails checking authorization. Since 0.9.1 What is a colon-separated list of lock types. The list of lock types are: shutdown, sleep, idle, handle-power-key, handle-suspend-key, handle-hibernate-key. Example: "shutdown:idle" Who is a human-readable, descriptive string of who is taking the lock. Example: "Xfburn" Why is a human-readable, descriptive string of why the program is taking the lock. Example: "Burning a DVD, interrupting now will ruin the DVD." Mode is either "block" or "delay" which determines if the inhibit lock is mandatory or should just delay the operation to a certain maximum time. Returns a file descriptor that encapsulates the lock, or -1 on failure. As soon as the file descriptor is closed (and all its duplicates) the lock is automatically released. If the client dies while the lock is taken it is automatically closed and the lock is released. Inhibit locks are named pipes used by ConsoleKit2 to prevent the system from performing actions such as suspending, restarting, or going idle. There are various reasons and application would like to prevent one or more of these functions such as a movie player preventing the screen saving from activating or a package manager ensuring an application installs before allowing the computer to shutdown. Note: Each application can have only one lock open at any given time. Multiple applications can hold locks to the same thing, for example a media player application and a cd burning application can both prevent the system from being marked idle. May fail with: CK_MANAGER_ERROR_INVALID_INPUT, CK_MANAGER_ERROR_OOM, CK_MANAGER_ERROR_GENERAL Since 0.9.0 See this simple example: DBusConnection *bus_connection; DBusMessage *message = NULL, *reply = NULL; DBusError error; gint fd = -1; const char *what = "shutdown:sleep"; const char *who = "Xfburn"; const char *why = "Burning a DVD, interrupting now will ruin the DVD."; const char *mode = "block"; message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", "Inhibit"); if (!message) { g_warning ("Unable to call Inhibit()"); return fd; } if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &what, DBUS_TYPE_STRING, &who, DBUS_TYPE_STRING, &why, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID)) { g_warning ("Unable to call Inhibit()"); dbus_message_unref (message); return fd; } reply = dbus_connection_send_with_reply_and_block (bus_connection, message, -1, &error); if (!reply) { g_warning ("Unable to inhibit: %s", error.message); dbus_message_unref (message); return fd; } if (!dbus_message_get_args (reply, &error, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID)) { g_warning ("Inhibit() reply parsing failed: %s", error.message); } dbus_message_unref (message); dbus_message_unref (reply); dbus_error_free (&error); return fd; This method emulates the logind implementation. Returns the current list of inhibitors, an array of strings representing the what, who, why, mode, and two unsigned int32 representing the user ID and process ID. May fail with: CK_MANAGER_ERROR_GENERAL or CK_MANAGER_ERROR_NOTHING_INHIBITED. Since 0.9.5 The secret cookie that is used to identify the new session This method requests that a new Session be created for the calling process. The properties of this new Session are set automatically from information collected about the calling process. This new session exists until the calling process disconnects from the system bus or calls CloseSession(). It is the responsibility of the calling process to set the environment variable XDG_SESSION_COOKIE to the value of the returned cookie. This cookie should only be made available to child processes of the caller so that they may be identified as members of this session. May fail with: CK_MANAGER_ERROR_GENERAL See this simple example: DBusError error; DBusMessage *message; DBusMessage *reply; message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", "OpenSession"); if (message == NULL) { goto out; } dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (connector->connection, message, -1, &error); if (reply == NULL) { goto out; } dbus_error_init (&error); if (! dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &cookie, DBUS_TYPE_INVALID)) { goto out; } OpenSessionWithParameters() An array of sets of property names and values The secret cookie that is used to identify the new session This method requests that a new Session be created for the calling process. The properties of this new Session are from the parameters provided. This new session exists until the calling process disconnects from the system bus or calls CloseSession(). It is the responsibility of the calling process to set the environment variable XDG_SESSION_COOKIE to the value of the returned cookie. This cookie should only be made available to child processes of the caller so that they may be identified as members of this session. See the Session properties for a list of valid parameters. May fail with: CK_MANAGER_ERROR_GENERAL org.freedesktop.ConsoleKit.Session This method is restricted to privileged users by D-Bus policy. The secret cookie that is used to identify the session Whether the session was successfully closed This method is used to close the session identified by the supplied cookie. The session can only be closed by the same process that opened the session. The session to activate This method is used to activate the specified session. May fail with: CK_MANAGER_ERROR_INVALID_INPUT, CK_MANAGER_ERROR_NO_SEATS, CK_MANAGER_ERROR_GENERAL Since 1.2.0 The session to activate The seat to activate the session on This method is used to activate the specified session as as long as it's on the seat_id. May fail with: CK_MANAGER_ERROR_INVALID_INPUT, CK_MANAGER_ERROR_GENERAL Since 1.2.0 The session to lock This will cause a Lock signal to be emitted for this session. This method is restricted to privileged users by D-Bus policy. Lock signal The session to unlock This will cause an Unlock signal to be emitted for this session. This can be used by login managers to unlock a session before it is re-activated during fast-user-switching. This method is restricted to privileged users by D-Bus policy. Unlock signal an array of seat names and IDs Retrieves a list of all Seats that are present on the system. Like the logind method of the same name, this returns both the seat's name (such as "seat0") and the D-Bus object path for the seat object that implements the Seat interface. GetSeats() an array of Seat IDs This gets a list of all the Seats that are currently present on the system. Each Seat ID is an D-Bus object path for the object that implements the Seat interface. org.freedesktop.ConsoleKit.Seat an array of Session IDs This gets a list of all the Sessions that are currently present on the system. Each Session ID is an D-Bus object path for the object that implements the Session interface. org.freedesktop.ConsoleKit.Session The secret cookie that is used to identify the session The object identifier for the current session Returns the session ID that is associated with the specified cookie. May fail with: CK_MANAGER_ERROR_GENERAL The POSIX process ID The object identifier for the current session Attempts to determine the session ID for the specified POSIX process ID (pid). May fail with: CK_MANAGER_ERROR_GENERAL The POSIX process ID The object identifier for the current session Attempts to determine the session ID for the specified POSIX process ID (pid). May fail with: CK_MANAGER_ERROR_GENERAL Since 1.1.1 The object identifier for the current session Attempts to determine the session ID that the caller belongs to. May fail with: CK_MANAGER_ERROR_GENERAL See this example of using dbus-send: dbus-send --system --dest=org.freedesktop.ConsoleKit \ --type=method_call --print-reply --reply-timeout=2000 \ /org/freedesktop/ConsoleKit/Manager \ org.freedesktop.ConsoleKit.Manager.GetCurrentSession POSIX User identification an array of Session IDs This gets a list of all the Sessions that are currently open for the specified user. Each Session ID is an D-Bus object path for the object that implements the Session interface. User identification an array of Session IDs This gets a list of all the Sessions that are currently open for the specified user. Each Session ID is an D-Bus object path for the object that implements the Session interface. The value of the system-idle-hint Returns TRUE if the idle-hint property of every open session is TRUE or if there are no open sessions. An ISO 8601 format date-type string Returns an ISO 8601 date-time string that corresponds to the time of the last change of the system-idle-hint. The Seat ID for the added seat Emitted when a Seat has been added to the system. The Seat ID for the removed seat Emitted when a Seat has been removed from the system. The Session ID for the added session The object path for the added session Emitted when a session has been added to the system. Since 1.1.1 The Session ID for the removed session The object path for the removed session Emitted when a session has been removed from the system. Since 1.1.1 The value of the system-idle-hint Emitted when the value of the system-idle-hint has changed. TRUE when the system is starting to halt. Emitted when the system is halting (active = TRUE). If successful there will not be a FALSE signal emitted since the system will poweroff or reboot. It will emit a FALSE signal if the shutdown operation failed. TRUE when starting to sleep. Emitted when the system is starting the sleep process. It will emit with an active = FALSE when resuming from sleep or if the sleep operation failed. consolekit2-1.2.6/src/org.freedesktop.ConsoleKit.Seat.xml000066400000000000000000000155431446640754400233600ustar00rootroot00000000000000 A seat is a collection of sessions and a set of hardware (usually at least a keyboard and mouse). Only one session may be active on a seat at a time. Seat ID Returns the ID for Seat. Seat Name Returns the name for Seat, such as Seat0. Since 1.1.1 an array of Session IDs This gets a list of all the Sessions that are currently attached to this seat. Each Session ID is an D-Bus object path for the object that implements the Session interface. an array of devices This gets a list of all the devices that are currently associated with this seat. Each device is an D-Bus structure that represents the device type and the device id. Session ID Gets the Session ID that is currently active on this Seat. Fails with CK_SEAT_ERROR_NO_ACTIVE_SESSION if there is no active session. TRUE if seat supports session activation Used to determine whether the seat supports session activation. Session ID Attempt to activate the specified session. In most cases, if successful, this will cause the session to become visible and take control of the hardware that is associated with this seat. May fail with: CK_SEAT_ERROR_FAILED, CK_SEAT_ERROR_ALREADY_ACTIVE, CK_SEAT_ERROR_NOT_SUPPORTED Activate() Virtual Terminal to switch to. Attempt to activate the specified VT. In most cases, if successful, this will cause the session to become visible and take control of the hardware that is associated with this seat. May fail with: CK_SEAT_ERROR_FAILED, CK_SEAT_ERROR_ALREADY_ACTIVE, CK_SEAT_ERROR_NOT_SUPPORTED, CK_SEAT_ERROR_GENERAL Since 1.1.1 Activate() Session ID Emitted when the active session has changed. Session ID Emitted when a session has been added to the seat. Session ID Emitted when a session has been removed from the seat. Device structure Emitted when a device has been associated with the seat. Device structure Emitted when a device has been dissociated from the seat. The Seat's name, such as Seat0 Since 1.1.1 consolekit2-1.2.6/src/org.freedesktop.ConsoleKit.Session.xml000066400000000000000000000766731446640754400241220ustar00rootroot00000000000000 Session objects represent and store information related to a user session. The properties associated with the Session specifically refer to the properties of the "session leader". Session ID Returns the ID for Session. Seat ID Returns the ID for the Seat the Session is attached to. May fail with CK_SESSION_ERROR_FAILED if the session isn't attached to a seat org.freedesktop.ConsoleKit.Seat Session service Returns the service of the provided session. Defaults to: "unspecified" - Unknown session type, the default. session-service Session type Returns the display type of the provided session. The following type may be returned: "x11" - An X11/Xorg based session "wayland" - A Wayland based session "tty" - A text console based session "mir" - A session using the Mir display server "unspecified" - Unknown session type, the default. Note: Additional types may be added in the future. session-type Session class Returns the display type of the provided session. The following classes may be returned: "user" - A normal user session, the default "greeter" - Display Manager pseudo session "lock-screen" - Screensaver based session "background" - A long running background process that requires its own session Note: Additional classes may be added in the future. Since 1.1.2 session-class Session state Returns the current state of the session. The following states may be returned: "online" - Session is logged in but not active "active" - Session is logged in and active "closing" - Session is in the process of shutting down Note: Additional classes may be added in the future. Since 1.1.2 session-state User ID Returns the user that the session belongs to. user POSIX User ID Returns the POSIX user ID that the session belongs to. unix-user XDG_RUNTIME_DIR Returns the XDG_RUNTIME_DIR location of the session. The XDG_RUNTIME_DIR is the same for all sessions of the same user and will be automatically removed once the last session of the user is closed. May fail with: CK_SESSION_ERROR_FAILED if it failed to create a runtime dir for the user (such as root). Since 1.1.0 The value of the X11 display Returns the value of the X11 DISPLAY for this session if one is present. x11-display The value of the X11 display device Returns the value of the display device (aka TTY) that the X11 display for the session is connected to. If there is no x11-display set then this value is undefined. x11-display-device The value of the display device Returns the value of the display device (aka TTY) that the session is connected to. display-device The remote host name Returns the value of the remote host name for the session. remote-host-name The value of the native system login session ID Returns the value of the login session ID that the underlying system uses to enforce session boundaries. If there is no login session ID set then this value is an empty string. The virtual terminal the session runs on, if any, 0 otherwise Returns the value of the virtual terminal that the underlying session runs on. If the seat doesn't support VTs, then this will always return 0. Since 1.1.2 TRUE if the session is active, otherwise FALSE Returns whether the session is active on the Seat that it is attached to. If the session is not attached to a seat this value is undefined. active TRUE if the session is local, otherwise FALSE Returns whether the session is local FIXME: we need to come up with a concrete definition for this value. It was originally used as a way to identify XDMCP sessions that originate from a remote system. is-local An ISO 8601 format date-type string Returns an ISO 8601 date-time string that corresponds to the time that the session was opened. Attempt to activate the this session. In most cases, if successful, this will cause the session to become visible and become active on the seat that it is attached to. May fail with: CK_SESSION_ERROR_ALREADY_ACTIVE, CK_SESSION_ERROR_NOT_SUPPORTED, CK_SESSION_ERROR_GENERAL Seat.ActivateSession() This will cause a Lock signal to be emitted for this session. This method is restricted to privileged users by D-Bus policy. Lock signal This will cause an Unlock signal to be emitted for this session. This can be used by login managers to unlock a session before it is re-activated during fast-user-switching. This method is restricted to privileged users by D-Bus policy. Unlock signal The value of the idle-hint Gets the value of the idle-hint property. idle-hint An ISO 8601 format date-type string Returns an ISO 8601 date-time string that corresponds to the time of the last change of the idle-hint. boolean value to set the idle-hint to This may be used by the session to indicate that it is idle. Use of this method is restricted to the user that owns the session. boolean value to set the locked-hint to This is used by Desktop Environments to update the LockedHint property. Calling Lock() or Unlock() will also update the LockedHint value. Use of this method is restricted to the user that owns the session. Whether the system supports a session controller. Returns TRUE if the system has Session Controller support. This means the TakeControl call won't return CK_SESSION_ERROR_NOT_SUPPORTED. Since 1.3.0 If set to TRUE, an existing session controller is replaced. Allows a single process per session to request ConsoleKit2 managed devices by calling TakeDevice. Use of this method is restricted to the user that owns the session or root. The force argument will be honored for root only. May fail with: CK_SESSION_ERROR_FAILED, CK_SESSION_ERROR_INSUFFICIENT_PERMISSION, CK_SESSION_ERROR_GENERAL, CK_SESSION_ERROR_NOT_SUPPORTED Since 1.1.1 The process that previously successfully called TakeControl may use this to reliqunish control. Any devices acquired with TakeDevice will be released. If the session controller closes the dbus-connection, this will implicitly call ReleaseControl. Use of this method is restricted to the process that called TakeControl. Since 1.1.1 Major number of the character-device. Minor number of the character-device. Returns a file descriptor for the specified device. boolean value if the deivce is currently inactive. ConsoleKit2 automatically mutes the file-descriptor if the session is inactive and resumes it once the session gets active again. This guarantees that a session can only access session-devices if the session is active. Note that this revoke/resume mechanism is asynchronous and may happen at any given time. This only works on devices that are attached to the seat of the given session. A process is not required to have direct access to the device-node. Also note that any device can only be requested once. As long as you don't release it, further calls will fail. Use of this method is restricted to the session-controller, see TakeControl. May fail with: CK_SESSION_ERROR_FAILED, CK_SESSION_ERROR_GENERAL, CK_SESSION_ERROR_NOT_SUPPORTED Since 1.1.1 Major number of the character-device. Minor number of the character-device. Release a previously acquired device. Use of this method is restricted to the session-controller, see TakeControl. Since 1.1.1 Major number of the character-device. Minor number of the character-device. Allows the session controller to synchronously pause a device in response to the PauseDevice signal. Forced signals are automatically completed by ConsoleKit2. Use of this method is restricted to the session-controller, see TakeControl. Since 1.1.1 Major number of the character-device. Minor number of the character-device. Will either be: force, pause, or gone Emitted for any device requested with TakeDevice. A device may remain paused for unknown reasons even though the Session is active. A type of 'force' means the device got paused by ConsoleKit2 already and this is only a notification. A type of 'pause' means ConsoleKit2 is requesting to pause the device and grants the session controller a limited amount of time to pause it. The session controller must respond to this via PauseDeviceComplete. This synchronous pausing-mechanism is used for backwards-compatibility to VTs and ConsoleKit2 is free to not make use of it. ConsoleKit2 may also send a force PauseDevice if you don't respond in a timely manner (or for any other reason). A type of 'gone' means the device was unplugged from the system and you will no longer get any notifications about it. Since 1.1.1 Major number of the character-device. Minor number of the character-device. Will either be: force, pause, or gone Emitted for any device requested with TakeDevice. Sent whenever a session is active and a device is resumed. It carries the major/minor as arguments and provides a new open file-descriptor. You should switch to the new descriptor and close the old one. They are not guaranteed to have the same underlying file descriptor. Since 1.1.1 TRUE if the session is active, otherwise FALSE Emitted when the active property has changed. the new value of idle-hint Emitted when the idle-hint property has changed. Emitted in response to a call to the Lock() method. It is intended that the screensaver for the session should lock the screen in response to this signal. Emitted in response to a call to the Unlock() method. It is intended that the screensaver for the session should unlock the screen in response to this signal. The user assigned to the session. The user assigned to the session. The seat the session is assigned to. It is comprised of the seat id and object path of the seat. The service of the session. The type of the session. The class of the session. The state of the session. The remote host name for the session. This will be set in situations where the session is opened and controlled from a remote system. For example, this value will be set when the session is created from an SSH or XDMCP connection. The display device (aka TTY) that the session is connected to. Value of the X11 DISPLAY for this session if one is present. The display device (aka TTY) that the X11 display for the session is connected to. If there is no x11-display set then this value is undefined. The virtual terminal the session runs on, if any, 0 otherwise. Whether the session is active on the Seat that it is attached to. If the session is not attached to a seat this value is undefined. Whether the session is local FIXME: we need to come up with a concrete definition for this value. It was originally used as a way to identify XDMCP sessions that originate from a remote system. This is a hint used to indicate that the session may be idle. For sessions with a x11-display set (ie. graphical sessions), it is up to each session to delegate the responsibility for updating this value. Typically, the screensaver will set this. However, for non-graphical sessions with a display-device set the Session object itself will periodically update this value based on the activity detected on the display-device itself. This should not be considered authoritative. This is a hint used by Desktop Environments to indicate that the session may be locked. consolekit2-1.2.6/src/test-event-logger.c000066400000000000000000000050341446640754400203020ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-event-logger.h" static gboolean write_to_log (CkEventLogger *logger) { CkLogEvent event; GError *error; gboolean res; memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SEAT_SESSION_ADDED; g_get_current_time (&event.timestamp); event.event.seat_session_added.session_id = "Session1"; error = NULL; res = ck_event_logger_queue_event (logger, &event, &error); if (! res) { g_warning ("Unable to queue event: %s", error->message); g_error_free (error); } return TRUE; } int main (int argc, char **argv) { GMainLoop *loop; CkEventLogger *logger; char *filename; #if !GLIB_CHECK_VERSION(2, 32, 0) if (! g_thread_supported ()) { g_thread_init (NULL); } #endif #if !GLIB_CHECK_VERSION(2, 36, 0) g_type_init (); #endif filename = g_build_filename (g_get_tmp_dir (), "ck-logger-test.log", NULL); g_message ("Testing the event logger.\n Should write messages to: %s", filename); logger = ck_event_logger_new (filename); g_free (filename); g_timeout_add (1000, (GSourceFunc)write_to_log, logger); loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); g_object_unref (logger); g_main_loop_unref (loop); return 0; } consolekit2-1.2.6/src/test-fus000077500000000000000000000042021446640754400162570ustar00rootroot00000000000000#!/usr/bin/env python # # Test fast-user-switch functionality # import os import sys import gobject import dbus import dbus.glib def activate_reply (res): print "session activated" def activate_error (e): print str (e) def session_added_cb (ssid): print "Session added: %s" % ssid def session_removed_cb (ssid): print "Session removed: %s" % ssid def active_session_changed_cb (ssid): print "Active session changed: %s" % ssid bus = dbus.SystemBus () manager_obj = bus.get_object ('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/Manager') manager = dbus.Interface (manager_obj, 'org.freedesktop.ConsoleKit.Manager') current_ssid = manager.GetCurrentSession () current_session_obj = bus.get_object ('org.freedesktop.ConsoleKit', current_ssid) current_session = dbus.Interface (current_session_obj, 'org.freedesktop.ConsoleKit.Session') sid = current_session.GetSeatId () if not sid: print "Current session is not attached to a seat, no switching possible" sys.exit () seat_obj = bus.get_object ('org.freedesktop.ConsoleKit', sid) seat = dbus.Interface (seat_obj, 'org.freedesktop.ConsoleKit.Seat') seat.connect_to_signal ('SessionAdded', session_added_cb) seat.connect_to_signal ('SessionRemoved', session_removed_cb) seat.connect_to_signal ('ActiveSessionChanged', active_session_changed_cb) can_fus = seat.CanActivateSessions() if can_fus: print "The current seat supports session switching" else: print "The current seat does not support session switching" # Show a list of sessions on the current seat sessions = seat.GetSessions () for ssid in sessions: session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid) session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session') uid = session.GetUser () print "Session %s user=%u" % (ssid, uid) # then pretend a session-ID is selected: ssid = current_ssid session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid) session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session') session.Activate (reply_handler = activate_reply, error_handler = activate_error) mainloop = gobject.MainLoop () mainloop.run() consolekit2-1.2.6/src/test-inhibit.c000066400000000000000000000156501446640754400173370ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "ck-inhibit.h" #include "ck-inhibit-manager.h" static const gchar* WHO = "test-inhibit"; static const gchar* WHAT = "sleep:idle"; static const gchar* WHY = "for testing"; static const gchar* MODE = "block"; /* If this doesn't get escaped we won't have rights to write here */ static const gchar* WHO2 = "../../../../../root"; static const gchar* WHAT2 = "shutdown:sleep"; static const gchar* MODE2 = "delay"; CkInhibitManager *manager; CkInhibit *inhibit; gint fd, fd1, fd2; static void test_create_inhibit (void) { /* Let's not overwrite our object */ g_assert (inhibit == NULL); inhibit = ck_inhibit_new (); /* Verify we got a valid inhibit object */ g_assert (inhibit != NULL); g_assert (CK_IS_INHIBIT (inhibit)); } static void test_ck_create_inhibit_lock (void) { /* sanity checks */ g_assert (fd == -1); g_assert (CK_IS_INHIBIT (inhibit)); fd = ck_inhibit_create_lock (inhibit, WHO, WHAT, WHY, MODE, 42, 9999); /* ensure we succeeded */ g_assert (fd >= 0); } static void test_which_are_inhibited (void) { /* sanity checks */ g_assert (fd != -1); g_assert (CK_IS_INHIBIT (inhibit)); /* these should test false */ g_assert (ck_inhibit_is_shutdown_inhibited (inhibit) == FALSE); g_assert (ck_inhibit_is_power_key_inhibited (inhibit) == FALSE); g_assert (ck_inhibit_is_suspend_key_inhibited (inhibit) == FALSE); g_assert (ck_inhibit_is_hibernate_key_inhibited (inhibit) == FALSE); /* these should test true */ g_assert (ck_inhibit_is_suspend_inhibited (inhibit)); g_assert (ck_inhibit_is_idle_inhibited (inhibit)); } static void test_close_inhibit_lock (void) { /* do we have a fd? */ g_assert (fd >= 0); /* does it properly close? */ g_assert (g_close (fd, NULL)); /* verify we can't close it again */ g_assert (g_close (fd, NULL) == FALSE); fd = -1; } static void test_unref_inhibit (void) { /* Verify we have an inhibit object */ g_assert (inhibit != NULL); g_assert (CK_IS_INHIBIT (inhibit)); g_object_unref (inhibit); inhibit = NULL; } static void cb_changed_event (CkInhibitManager *ckmanager, gint inhibit_mode, gint event, gboolean enabled, gpointer user_data) { g_print ("cb_changed_event: mode %s event %d is now %s\n", inhibit_mode == CK_INHIBIT_MODE_BLOCK ? "CK_INHIBIT_MODE_BLOCK" : inhibit_mode == CK_INHIBIT_MODE_DELAY ? "CK_INHIBIT_MODE_DELAY" : "unknown", event, enabled ? "TRUE" : "FALSE"); } static void test_manager_init (void) { manager = ck_inhibit_manager_get (); g_assert (CK_IS_INHIBIT_MANAGER (manager)); g_signal_connect (manager, "changed-event", G_CALLBACK (cb_changed_event), NULL); } static void test_manager_add_lock1 (void) { g_print ("\n"); fd1 = ck_inhibit_manager_create_lock (manager, WHO, WHAT, WHY, MODE, 123, 456); g_assert (fd1 != 0); } static void test_manager_add_lock2 (void) { g_print ("\n"); fd2 = ck_inhibit_manager_create_lock (manager, WHO2, WHAT2, WHY, MODE2, 789, 987); g_assert (fd2 != 0); } static void test_manager_which_are_inhibited (void) { g_assert (ck_inhibit_manager_is_shutdown_delayed (manager)); g_assert (ck_inhibit_manager_is_suspend_blocked (manager)); g_assert (ck_inhibit_manager_is_idle_blocked (manager)); g_assert (ck_inhibit_manager_is_hibernate_key_blocked (manager) == FALSE); g_assert (ck_inhibit_manager_is_suspend_key_blocked (manager) == FALSE); g_assert (ck_inhibit_manager_is_power_key_blocked (manager) == FALSE); } static void test_manager_remove_lock1 (void) { g_print ("\n"); ck_inhibit_manager_remove_lock (manager, WHO); } static void test_manager_remove_lock2 (void) { g_print ("\n"); ck_inhibit_manager_remove_lock (manager, WHO2); } static void test_manager_unref (void) { g_object_unref (manager); } int main (int argc, char *argv[]) { /* do not run these tests as root */ if (getuid () == 0) { g_warning ("You must NOT be root to run these tests"); exit (1); } g_test_init (&argc, &argv, NULL); inhibit = NULL; fd = -1; /* Create the inhibit object */ g_test_add_func ("/inhibit/create", test_create_inhibit); g_test_add_func ("/inhibit/ck_create_inhibit_lock", test_ck_create_inhibit_lock); g_test_add_func ("/inhibit/which_are_inhibited", test_which_are_inhibited); g_test_add_func ("/inhibit/close_inhibit_lock", test_close_inhibit_lock); /* Release the inhibit object */ g_test_add_func ("/inhibit/unref", test_unref_inhibit); /* Now let's try using the inhibit manager */ g_test_add_func ("/inhibit/test_manager_init", test_manager_init); g_test_add_func ("/inhibit/test_manager_add_lock1", test_manager_add_lock1); g_test_add_func ("/inhibit/test_manager_add_lock2", test_manager_add_lock2); g_test_add_func ("/inhibit/test_manager_which_are_inhibited", test_manager_which_are_inhibited); g_test_add_func ("/inhibit/test_manager_remove_lock1", test_manager_remove_lock1); g_test_add_func ("/inhibit/test_manager_remove_lock2", test_manager_remove_lock2); g_test_add_func ("/inhibit/test_manager_unref", test_manager_unref); return g_test_run(); } consolekit2-1.2.6/src/test-manager.c000066400000000000000000000320301446640754400173120ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2015 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #define DBUS_NAME "org.freedesktop.ConsoleKit" #define DBUS_MANAGER_INTERFACE DBUS_NAME ".Manager" #define DBUS_SESSION_INTERFACE DBUS_NAME ".Session" #define DBUS_MANAGER_OBJECT_PATH "/org/freedesktop/ConsoleKit/Manager" GDBusProxy *manager; static void print_proxy_info (GDBusProxy *proxy) { g_print ("proxy info:\n" "name %s\n" "name owner %s\n" "object path %s\n" "interface name %s\n", g_dbus_proxy_get_name (proxy), g_dbus_proxy_get_name_owner (proxy), g_dbus_proxy_get_object_path (proxy), g_dbus_proxy_get_interface_name (proxy)); } static GVariant* print_method (GDBusProxy *proxy, const gchar *method, GVariant *variant) { GVariant *var; GError *error = NULL; g_print ("calling %s\t", method); var = g_dbus_proxy_call_sync (proxy, method, variant, G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (var != NULL) { GString *string = g_variant_print_string (var, NULL, TRUE); g_print ("%s", string->str); } else { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); } g_clear_error (&error); g_print ("\n"); return var; } static void print_reply (GDBusProxy *proxy, const gchar *method) { GVariant *var = print_method (proxy, method, g_variant_new ("()")); if (var) g_variant_unref (var); } static gint print_inhibit_reply (GDBusProxy *proxy, const gchar *method) { GVariant *var; gint fd = -1; GError *error = NULL; GUnixFDList *out_fd_list = NULL; g_print ("calling %s\t", method); var = g_dbus_proxy_call_with_unix_fd_list_sync (proxy, method, g_variant_new ("(ssss)", "sleep:shutdown", "test-manager", "testing inhibit", "block"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &out_fd_list, NULL, &error); if (var != NULL) { GString *string = g_variant_print_string (var, NULL, TRUE); g_print ("%s", string->str); fd = g_unix_fd_list_get (out_fd_list, 0, NULL); g_print ("fd %d", fd); } else { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_variant_unref (var); } g_clear_error (&error); g_print ("\n"); return fd; } static gboolean validate_session (const gchar *path) { GDBusProxy *session; GError *error = NULL; g_print ("entering validate_stuff for %s\n", path); session = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, DBUS_NAME, path, DBUS_SESSION_INTERFACE, NULL, &error); if (session == NULL || error != NULL) { if (error != NULL) { g_printerr ("Error creating session proxy: %s\n", error->message); g_clear_error (&error); } return FALSE; } print_proxy_info (session); print_reply (session, "GetId"); print_reply (session, "GetSeatId"); print_reply (session, "GetSessionType"); print_reply (session, "GetSessionClass"); print_reply (session, "GetSessionState"); print_reply (session, "GetUser"); print_reply (session, "GetUnixUser"); print_reply (session, "GetX11Display"); print_reply (session, "GetX11DisplayDevice"); print_reply (session, "GetDisplayDevice"); print_reply (session, "GetVTNr"); print_reply (session, "GetRemoteHostName"); print_reply (session, "GetLoginSessionId"); print_reply (session, "IsActive"); print_reply (session, "IsLocal"); print_reply (session, "GetCreationTime"); print_reply (session, "GetIdleHint"); print_reply (session, "GetIdleSinceHint"); g_print ("done printing stuff for %s\n\n", path); g_object_unref (session); return TRUE; } static void open_print_and_test_session (GDBusProxy *proxy, const gchar *method) { GVariantBuilder ck_parameters; GVariant *open_var = NULL; GVariant *ssid_var = NULL; GVariant *close_var = NULL; GVariant *activate_var = NULL; GError *error = NULL; const gchar *cookie; const gchar *ssid; gboolean is_session_closed; /* Build the params so we can call OpenSessionWithParameters. This * is copied from LightDM (with fake values), so we can verify it * works as expected */ g_variant_builder_init (&ck_parameters, G_VARIANT_TYPE ("(a(sv))")); g_variant_builder_open (&ck_parameters, G_VARIANT_TYPE ("a(sv)")); g_variant_builder_add (&ck_parameters, "(sv)", "unix-user", g_variant_new_int32 (9000)); g_variant_builder_add (&ck_parameters, "(sv)", "session-type", g_variant_new_string ("tty")); g_variant_builder_add (&ck_parameters, "(sv)", "session-class", g_variant_new_string ("greeter")); g_variant_builder_add (&ck_parameters, "(sv)", "x11-display", g_variant_new_string (":0.0")); g_variant_builder_add (&ck_parameters, "(sv)", "x11-display-device", g_variant_new_string ("/dev/tty15")); g_variant_builder_add (&ck_parameters, "(sv)", "is-local", g_variant_new_boolean (TRUE)); g_print ("calling %s\t", method); open_var = g_dbus_proxy_call_sync (proxy, method, g_variant_new ("(a(sv))", &ck_parameters), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (open_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); goto out; } g_variant_get (open_var, "(s)", &cookie); g_print ("cookie: %s", cookie); g_print ("\n"); /* Since we built a session go ahead and test getting the ssid */ g_print ("calling GetSessionForCookie\t"); ssid_var = g_dbus_proxy_call_sync (proxy, "GetSessionForCookie", g_variant_new ("(s)", cookie), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (ssid_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); goto out; } g_variant_get (ssid_var, "(o)", &ssid); g_print ("ssid: %s", ssid); g_print ("\n"); validate_session (ssid); g_print ("calling LockSession (expected: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied if not run as root)\n"); activate_var = g_dbus_proxy_call_sync (proxy, "LockSession", g_variant_new ("(s)", ssid), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (activate_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); } if (activate_var) g_variant_unref (activate_var); g_print ("calling UnlockSession (expected: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied if not run as root)\n"); activate_var = g_dbus_proxy_call_sync (proxy, "UnlockSession", g_variant_new ("(s)", ssid), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (activate_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); } if (activate_var) g_variant_unref (activate_var); /* test closing our session */ g_print ("calling CloseSession\t"); close_var = g_dbus_proxy_call_sync (proxy, "CloseSession", g_variant_new ("(s)", cookie), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (close_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); goto out; } g_variant_get (close_var, "(b)", &is_session_closed); g_print ("session closed? %s", is_session_closed ? "Closed" : "Not Closed"); g_print ("\n"); out: g_clear_error (&error); if (ssid_var != NULL) g_variant_unref (ssid_var); if (open_var != NULL) g_variant_unref (open_var); if (close_var != NULL) g_variant_unref (close_var); g_print ("\n"); } static gboolean validate_stuff (void) { gint fd; GVariant *session_var = NULL, *close_var = NULL; gboolean is_session_closed; GError *error = NULL; print_reply (manager, "CanRestart"); print_reply (manager, "CanStop"); print_reply (manager, "CanReboot"); print_reply (manager, "CanPowerOff"); print_reply (manager, "CanSuspend"); print_reply (manager, "CanHibernate"); print_reply (manager, "CanHybridSleep"); fd = print_inhibit_reply (manager, "Inhibit"); session_var = print_method (manager, "OpenSession", g_variant_new ("()")); print_reply (manager, "GetSeats"); print_reply (manager, "GetSessions"); print_reply (manager, "GetCurrentSession"); print_reply (manager, "GetSystemIdleHint"); print_reply (manager, "GetSystemIdleSinceHint"); open_print_and_test_session (manager, "OpenSessionWithParameters"); print_reply (manager, "ListInhibitors"); if (fd > -1) { g_print ("Expecting an Error.Inhibited message\n"); print_method (manager, "Suspend", g_variant_new ("(b)", FALSE)); g_close (fd, NULL); } /* test closing our session */ if (session_var != NULL) { g_print ("calling CloseSession\t"); close_var = g_dbus_proxy_call_sync (manager, "CloseSession", session_var, G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (close_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); } } g_variant_get (close_var, "(b)", &is_session_closed); g_print ("session closed? %s\n", is_session_closed ? "Closed" : "Not Closed"); g_print ("done printing stuff\n\n"); if (session_var) g_variant_unref (session_var); if (close_var) g_variant_unref (close_var); return TRUE; } int main (int argc, char *argv[]) { GError *error = NULL; g_setenv ("G_DEBUG", "fatal_criticals", FALSE); g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); manager = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, DBUS_NAME, DBUS_MANAGER_OBJECT_PATH, DBUS_MANAGER_INTERFACE, NULL, &error); if (manager == NULL || error != NULL) { if (error != NULL) { g_printerr ("Error creating manager proxy: %s\n", error->message); g_clear_error (&error); } return FALSE; } print_proxy_info (manager); g_print ("\n"); validate_stuff (); g_object_unref (manager); return 0; } consolekit2-1.2.6/src/test-method-access-policy000077500000000000000000000355721446640754400215140ustar00rootroot00000000000000#!/usr/bin/env python # # Test access to methods # import os import sys import gobject import dbus import dbus.glib bus = dbus.SystemBus () privileged = (os.geteuid () == 0) if privileged: print "Running privileged as uid=%d pid=%d" % (os.geteuid (), os.getpid ()) else: print "Running unprivileged as uid=%d pid=%d" % (os.geteuid (), os.getpid ()) print "Testing all public methods to check D-Bus policy" manager_obj = bus.get_object ('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/Manager') manager = dbus.Interface (manager_obj, 'org.freedesktop.ConsoleKit.Manager') print "Testing Manager" print "Testing Manager.OpenSession:", res = "PASS" try: cookie = manager.OpenSession () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Manager.CloseSession:", res = "PASS" try: manager.CloseSession (cookie) except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Manager.OpenSessionWithParameters:", res = "PASS" try: cookie = manager.OpenSessionWithParameters (dbus.Array([], signature = "sv")) if not privileged: res = "FAIL" except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": if privileged: res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t%s" % res print "Testing Manager.GetSeats:", res = "PASS" try: manager.GetSeats () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Manager.GetSessionForCookie:", res = "PASS" try: manager.GetSessionForCookie (os.environ['XDG_SESSION_COOKIE']) except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Manager.GetSessionForUnixProcess:", res = "PASS" try: manager.GetSessionForUnixProcess (os.getpid ()) except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t%s" % res print "Testing Manager.GetCurrentSession:", res = "PASS" try: manager.GetCurrentSession () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Manager.GetSessionsForUnixUser:", res = "PASS" try: manager.GetSessionsForUnixUser (os.geteuid ()) except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t%s" % res print "Testing Manager.GetSessionsForUser:", res = "PASS" try: manager.GetSessionsForUser (os.geteuid ()) except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Manager.GetSystemIdleHint:", res = "PASS" try: manager.GetSystemIdleHint () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Manager.GetSystemIdleSinceHint:", res = "PASS" try: manager.GetSystemIdleSinceHint () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t%s" % res # Test Seat Interface print "Testing Seat" seat_obj = bus.get_object ('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/seat0') seat = dbus.Interface (seat_obj, 'org.freedesktop.ConsoleKit.Seat') print "Testing Seat.GetId:", res = "PASS" try: seat.GetId () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t\t%s" % res print "Testing Seat.GetSessions:", res = "PASS" try: seat.GetSessions () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Seat.GetDevices:", res = "PASS" try: seat.GetDevices () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Seat.GetActiveSession:", res = "PASS" try: seat.GetActiveSession () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Seat.CanActivateSessions:", res = "PASS" try: seat.CanActivateSessions () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Seat.ActivateSession:", res = "PASS" try: seat.ActivateSession ('/org/freedesktop/ConsoleKit/SessionN') except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res # Test Session Interface print "Testing Session" # create a new session so we can set props cookie = manager.OpenSession () ssid = manager.GetSessionForCookie (cookie) if not ssid: print "Could not create a session to test" sys.exit () session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid) session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session') print "Testing Session.GetId:", res = "PASS" try: session.GetId () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t\t%s" % res print "Testing Session.GetSeatId:", res = "PASS" try: session.GetSeatId () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Session.GetLoginSessionId:", res = "PASS" try: session.GetLoginSessionId () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Session.GetSessionType:", res = "PASS" try: session.GetSessionType () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Session.GetUser:", res = "PASS" try: session.GetUser () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Session.GetUnixUser:", res = "PASS" try: session.GetUnixUser () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Session.GetX11Display:", res = "PASS" try: session.GetX11Display () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Session.GetX11DisplayDevice:", res = "PASS" try: session.GetX11DisplayDevice () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Session.GetDisplayDevice:", res = "PASS" try: session.GetDisplayDevice () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Session.GetRemoteHostName:", res = "PASS" try: session.GetRemoteHostName () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Session.IsActive:", res = "PASS" try: session.IsActive () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Session.IsLocal:", res = "PASS" try: session.IsLocal () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Session.GetCreationTime:", res = "PASS" try: session.GetCreationTime () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Session.Activate:", res = "PASS" try: session.Activate () except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res print "Testing Session.Lock:", res = "PASS" try: session.Lock () if not privileged: res = "FAIL" except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": if privileged: res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t\t%s" % res print "Testing Session.Unlock:", res = "PASS" try: session.Unlock () if not privileged: res = "FAIL" except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": if privileged: res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res # Test session properties session_props = dbus.Interface (session_obj, 'org.freedesktop.DBus.Properties') print "Testing Properties.Get 'unix-user':", res = "PASS" try: session_props.Get ('org.freedesktop.ConsoleKit.Session', "unix-user") if not privileged: res = "FAIL" except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": if privileged: res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Properties.Get 'cookie':", res = "PASS" try: session_props.Get ('org.freedesktop.ConsoleKit.Session', "cookie") if not privileged: res = "FAIL" except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": if privileged: res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t%s" % res print "Testing Properties.Set:", res = "PASS" try: session_props.Set ('org.freedesktop.ConsoleKit.Session', "unix-user", 0) if not privileged: res = "FAIL" except dbus.exceptions.DBusException, e: if e.get_dbus_name () == "org.freedesktop.DBus.Error.AccessDenied": if privileged: res = "FAIL" elif e.get_dbus_name () == "org.freedesktop.DBus.Error.UnknownMethod": res = "UKNOWN METHOD" except: pass print "\t\t\t%s" % res consolekit2-1.2.6/src/test-open-session000077500000000000000000000026301446640754400201070ustar00rootroot00000000000000#!/usr/bin/env python # # Test opening a new session # import os import gobject import dbus import dbus.glib print "uid=%d pid=%d" % (os.geteuid (), os.getpid ()) bus = dbus.SystemBus () manager_obj = bus.get_object ('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/Manager') manager = dbus.Interface (manager_obj, 'org.freedesktop.ConsoleKit.Manager') cookie = manager.OpenSession () os.environ['XDG_SESSION_COOKIE'] = cookie print "Got cookie: %s" % cookie seats = manager.GetSeats () for sid in seats: seat_obj = bus.get_object ('org.freedesktop.ConsoleKit', sid) seat = dbus.Interface (seat_obj, 'org.freedesktop.ConsoleKit.Seat') sessions = seat.GetSessions () for ssid in sessions: session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid) session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session') uid = session.GetUser () # Hmm looks like the proc environment doesn't get updated when # os.environ is set. So, we won't use GetCurrentSession. #current_session = manager.GetCurrentSession () current_session = manager.GetSessionForCookie (cookie) print "Current session: %s" % current_session session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid) session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session') mainloop = gobject.MainLoop () gobject.timeout_add (30000, mainloop.quit) mainloop.run() consolekit2-1.2.6/src/test-open-session-with-parameters000077500000000000000000000037701446640754400232270ustar00rootroot00000000000000#!/usr/bin/env python # # Test opening a new session # import os import gobject import dbus import dbus.glib bus = dbus.SystemBus () manager_obj = bus.get_object ('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/Manager') manager = dbus.Interface (manager_obj, 'org.freedesktop.ConsoleKit.Manager') params = dbus.Array ([], signature = "(sv)") params.append (("unix-user", dbus.Int32 (730, variant_level=1))) params.append (("session-type", dbus.String ("Unknown", variant_level=1))) #params.append (("x11-display", dbus.String (":0.0", variant_level=1))) params.append (("display-device", dbus.String ("/dev/tty8", variant_level=1))) params.append (("is-local", dbus.Boolean (True, variant_level=1))) params.append (("bogus-property", dbus.String ("Something bogus", variant_level=1))) params.append (("cookie", dbus.String ("This should be ignored", variant_level=1))) params.append (("id", dbus.String ("This should be ignored too", variant_level=1))) cookie = manager.OpenSessionWithParameters (params) os.environ['XDG_SESSION_COOKIE'] = cookie print "Got cookie: %s" % cookie seats = manager.GetSeats () for sid in seats: seat_obj = bus.get_object ('org.freedesktop.ConsoleKit', sid) seat = dbus.Interface (seat_obj, 'org.freedesktop.ConsoleKit.Seat') sessions = seat.GetSessions () for ssid in sessions: session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid) session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session') uid = session.GetUser () # The proc environment doesn't get updated when # os.environ is set. So, we won't use GetCurrentSession. #current_session = manager.GetCurrentSession () current_session = manager.GetSessionForCookie (cookie) print "Current session: %s" % current_session session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid) session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session') mainloop = gobject.MainLoop () gobject.timeout_add (30000, mainloop.quit) mainloop.run() consolekit2-1.2.6/src/test-seat.c000066400000000000000000000123341446640754400166410ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2015 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #define DBUS_NAME "org.freedesktop.ConsoleKit" #define DBUS_MANAGER_INTERFACE DBUS_NAME ".Manager" #define DBUS_SEAT_INTERFACE DBUS_NAME ".Seat" #define DBUS_MANAGER_OBJECT_PATH "/org/freedesktop/ConsoleKit/Manager" GDBusProxy *manager; static void print_proxy_info (GDBusProxy *proxy) { g_print ("proxy info:\n" "name %s\n" "name owner %s\n" "object path %s\n" "interface name %s\n", g_dbus_proxy_get_name (proxy), g_dbus_proxy_get_name_owner (proxy), g_dbus_proxy_get_object_path (proxy), g_dbus_proxy_get_interface_name (proxy)); } static void print_reply (GDBusProxy *proxy, const gchar *method) { GVariant *var; GError *error = NULL; g_print ("calling %s\t", method); var = g_dbus_proxy_call_sync (proxy, method, g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (var != NULL) { GString *string = g_variant_print_string (var, NULL, TRUE); g_print ("%s", string->str); } else { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); } g_clear_error (&error); if (var) g_variant_unref (var); g_print ("\n"); } static gboolean validate_stuff (const gchar *path) { GDBusProxy *seat; GError *error = NULL; g_print ("entering validate_stuff for %s\n", path); seat = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, DBUS_NAME, path, DBUS_SEAT_INTERFACE, NULL, &error); if (seat == NULL || error != NULL) { if (error != NULL) { g_printerr ("Error creating seat proxy: %s\n", error->message); g_clear_error (&error); } return FALSE; } print_proxy_info (seat); print_reply (seat, "GetId"); print_reply (seat, "GetSessions"); print_reply (seat, "GetDevices"); print_reply (seat, "CanActivateSessions"); print_reply (seat, "GetActiveSession"); g_print ("done printing stuff for %s\n\n", path); g_object_unref (seat); return TRUE; } static gboolean get_seats (gpointer user_data) { GVariant *var; GVariantIter *iter; GError *error = NULL; gchar *path = NULL; g_print ("calling GetSeats\n"); var = g_dbus_proxy_call_sync (manager, "GetSeats", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); return FALSE; } g_variant_get (var, "(ao)", &iter); while (g_variant_iter_next (iter, "o", &path)) { validate_stuff (path); } g_variant_iter_free (iter); g_variant_unref (var); return FALSE; } int main (int argc, char *argv[]) { GError *error = NULL; g_setenv ("G_DEBUG", "fatal_criticals", FALSE); g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); manager = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, DBUS_NAME, DBUS_MANAGER_OBJECT_PATH, DBUS_MANAGER_INTERFACE, NULL, &error); if (manager == NULL || error != NULL) { if (error != NULL) { g_printerr ("Error creating manager proxy: %s\n", error->message); g_clear_error (&error); } return FALSE; } print_proxy_info (manager); g_print ("\n"); get_seats (NULL); g_object_unref (manager); return 0; } consolekit2-1.2.6/src/test-session-leader.c000066400000000000000000000070101446640754400206150ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include "ck-session-leader.h" #define UID 9000 #define PID 8999 #define SERVICE_NAME "test-session-leader" #define SESSION_ID "Session9999" #define COOKIE "test-session-leader-cookie" CkSessionLeader *leader = NULL; static void collect_parameters_cb (CkSessionLeader *ckleader, GVariant *parameters, GDBusMethodInvocation *context, GMainLoop *loop) { g_debug ("[collect_parameters_cb] Parameters: %s", g_variant_print (parameters, TRUE)); g_main_loop_quit (loop); } static void test_leader_init (void) { leader = ck_session_leader_new (); ck_session_leader_set_uid (leader, UID); ck_session_leader_set_pid (leader, PID); ck_session_leader_set_service_name (leader, SERVICE_NAME); ck_session_leader_set_session_id (leader, SESSION_ID); ck_session_leader_set_cookie (leader, COOKIE); /* Verify! */ g_assert (CK_IS_SESSION_LEADER (leader)); g_assert (ck_session_leader_get_uid (leader) == UID); g_assert (ck_session_leader_get_pid (leader) == PID); g_assert (g_strcmp0 (ck_session_leader_peek_service_name (leader), SERVICE_NAME) == 0); g_assert (g_strcmp0 (ck_session_leader_peek_session_id (leader), SESSION_ID) == 0); g_assert (g_strcmp0 (ck_session_leader_peek_cookie (leader), COOKIE) == 0); } static void test_leader_collect (void) { GMainLoop *loop; g_debug ("Setting up main loop"); loop = g_main_loop_new (NULL, FALSE); ck_session_leader_collect_parameters (leader, NULL, (CkSessionLeaderDoneFunc)collect_parameters_cb, loop); g_main_loop_run (loop); } static void test_leader_unref (void) { g_object_unref (leader); } int main (int argc, char *argv[]) { /* do not run these tests as root * execute with G_MESSAGES_DEBUG=all ./test-session-leader * for the printout of the parameters collected */ if (getuid () == 0) { g_warning ("You must NOT be root to run this tests"); exit (1); } g_test_init (&argc, &argv, NULL); g_test_add_func ("/test_session_leader/test_leader_init", test_leader_init); g_test_add_func ("/test_session_leader/test_leader_collect", test_leader_collect); g_test_add_func ("/test_session_leader/test_leader_unref", test_leader_unref); return g_test_run(); } consolekit2-1.2.6/src/test-session.c000066400000000000000000000230751446640754400173740ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2014 Eric Koegel * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #define DBUS_NAME "org.freedesktop.ConsoleKit" #define DBUS_MANAGER_INTERFACE DBUS_NAME ".Manager" #define DBUS_SESSION_INTERFACE DBUS_NAME ".Session" #define DBUS_MANAGER_OBJECT_PATH "/org/freedesktop/ConsoleKit/Manager" GDBusProxy *manager; static void print_proxy_info (GDBusProxy *proxy) { g_print ("proxy info:\n" "name %s\n" "name owner %s\n" "object path %s\n" "interface name %s\n", g_dbus_proxy_get_name (proxy), g_dbus_proxy_get_name_owner (proxy), g_dbus_proxy_get_object_path (proxy), g_dbus_proxy_get_interface_name (proxy)); } static void print_reply (GDBusProxy *proxy, const gchar *method) { GVariant *var; GError *error = NULL; g_print ("calling %s\t", method); var = g_dbus_proxy_call_sync (proxy, method, g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (var != NULL) { GString *string = g_variant_print_string (var, NULL, TRUE); g_print ("%s", string->str); } else { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); } g_clear_error (&error); if (var) g_variant_unref (var); g_print ("\n"); } static gboolean validate_stuff (const gchar *path) { GDBusProxy *session; GError *error = NULL; g_print ("entering validate_stuff for %s\n", path); session = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, DBUS_NAME, path, DBUS_SESSION_INTERFACE, NULL, &error); if (session == NULL || error != NULL) { if (error != NULL) { g_printerr ("Error creating session proxy: %s\n", error->message); g_clear_error (&error); } return FALSE; } print_proxy_info (session); print_reply (session, "GetId"); print_reply (session, "GetSeatId"); print_reply (session, "GetSessionType"); print_reply (session, "GetSessionClass"); print_reply (session, "GetSessionState"); print_reply (session, "GetUser"); print_reply (session, "GetUnixUser"); print_reply (session, "GetX11Display"); print_reply (session, "GetX11DisplayDevice"); print_reply (session, "GetDisplayDevice"); print_reply (session, "GetVTNr"); print_reply (session, "GetRemoteHostName"); print_reply (session, "GetLoginSessionId"); print_reply (session, "IsActive"); print_reply (session, "IsLocal"); print_reply (session, "GetCreationTime"); print_reply (session, "GetIdleHint"); print_reply (session, "GetIdleSinceHint"); g_print ("done printing stuff for %s\n\n", path); g_object_unref (session); return TRUE; } static gboolean get_sessions (gpointer user_data) { GVariant *var; GVariantIter *iter; GError *error = NULL; gchar *path = NULL; g_print ("calling GetSessions\n"); var = g_dbus_proxy_call_sync (manager, "GetSessions", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); return FALSE; } g_variant_get (var, "(ao)", &iter); while (g_variant_iter_next (iter, "o", &path)) { validate_stuff (path); } g_variant_iter_free (iter); g_variant_unref (var); return FALSE; } static void open_session (void) { GDBusProxy *session; GVariant *cookie_var, *session_var, *activate_var, *close_var; GError *error = NULL; const gchar *path = NULL, *cookie = NULL; g_print ("calling OpenSession\n"); cookie_var = g_dbus_proxy_call_sync (manager, "OpenSession", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (cookie_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); return; } g_variant_get (cookie_var, "(s)", &cookie, NULL); g_print ("calling GetSessionForCookie\n"); session_var = g_dbus_proxy_call_sync (manager, "GetSessionForCookie", g_variant_new ("(s)", cookie), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (session_var == NULL) { g_print ("returned NULL, is the daemon running?\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); return; } g_variant_get (session_var, "(o)", &path, NULL); session = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, DBUS_NAME, path, DBUS_SESSION_INTERFACE, NULL, &error); if (session == NULL || error != NULL) { if (error != NULL) { g_printerr ("Error creating session proxy: %s\n", error->message); g_clear_error (&error); } return; } validate_stuff (path); g_print ("calling Lock (expected: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied if not run as root)\n"); activate_var = g_dbus_proxy_call_sync (session, "Lock", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (activate_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); } if (activate_var) g_variant_unref (activate_var); g_print ("calling Unlock (expected: GDBus.Error:org.freedesktop.DBus.Error.AccessDenied if not run as root)\n"); activate_var = g_dbus_proxy_call_sync (session, "Unlock", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (activate_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); } if (activate_var) g_variant_unref (activate_var); g_print ("calling Activate (expected: GDBus.Error:org.freedesktop.ConsoleKit.Session.Error.NotSupported)\n"); activate_var = g_dbus_proxy_call_sync (session, "Activate", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (activate_var == NULL) { g_print ("returned NULL\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); } if (activate_var) g_variant_unref (activate_var); close_var = g_dbus_proxy_call_sync (manager, "CloseSession", g_variant_new ("(s)", cookie), G_DBUS_CALL_FLAGS_NONE, 3000, NULL, &error); if (close_var == NULL) { g_print ("Failed to close session\t"); if (error) g_print ("error %s", error->message); g_print ("\n"); g_clear_error (&error); return; } g_variant_unref (close_var); } int main (int argc, char *argv[]) { GError *error = NULL; g_setenv ("G_DEBUG", "fatal_criticals", FALSE); g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); manager = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, DBUS_NAME, DBUS_MANAGER_OBJECT_PATH, DBUS_MANAGER_INTERFACE, NULL, &error); if (manager == NULL || error != NULL) { if (error != NULL) { g_printerr ("Error creating manager proxy: %s\n", error->message); g_clear_error (&error); } return FALSE; } print_proxy_info (manager); open_session (); get_sessions (NULL); g_object_unref (manager); return 0; } consolekit2-1.2.6/src/test-tty-idle-monitor.c000066400000000000000000000054371446640754400211330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-tty-idle-monitor.h" #include "ck-sysdeps.h" static void idle_changed_cb (CkTtyIdleMonitor *monitor, gboolean idle_hint, gpointer data) { g_message ("idle hint changed: %s", idle_hint ? "idle" : "not idle"); } static gboolean is_console (const char *device) { int fd; gboolean ret; ret = FALSE; fd = open (device, O_RDONLY | O_NOCTTY); if (fd < 0) { goto out; } ret = ck_fd_is_a_console (fd, device); close (fd); out: return ret; } int main (int argc, char **argv) { GMainLoop *loop; CkTtyIdleMonitor *monitor; char *device; #if !GLIB_CHECK_VERSION(2, 36, 0) g_type_init (); #endif if (argc < 2) { device = ttyname (0); } else { device = g_strdup (argv[1]); } if (! is_console (device)) { g_warning ("Device is not a console"); exit (1); } g_message ("Testing the TTY idle monitor.\n1. Wait for idleness to be detected.\n2. Hit keys on the keyboard to see if activity is noticed."); monitor = ck_tty_idle_monitor_new (device); g_signal_connect (monitor, "idle-hint-changed", G_CALLBACK (idle_changed_cb), NULL); ck_tty_idle_monitor_set_threshold (monitor, 5); ck_tty_idle_monitor_start (monitor); loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); g_object_unref (monitor); g_main_loop_unref (loop); return 0; } consolekit2-1.2.6/src/test-vt-monitor.c000066400000000000000000000055141446640754400200250ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-vt-monitor.h" #include "ck-sysdeps.h" static void activated_cb (CkVtMonitor *monitor, guint num, gpointer data) { g_message ("VT %u activated", num); } int main (int argc, char **argv) { GMainLoop *loop; CkVtMonitor *monitor; GError *error; guint num; gboolean res; struct sigaction sa; #if !GLIB_CHECK_VERSION(2, 32, 0) if (! g_thread_supported ()) { g_thread_init (NULL); } #endif #if !GLIB_CHECK_VERSION(2, 36, 0) g_type_init (); #endif sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sigaction (SIGQUIT, &sa, NULL); sigaction (SIGHUP, &sa, NULL); if (! ck_is_root_user ()) { g_warning ("Must be run as root"); exit (1); } g_message ("Testing the VT monitor.\n Should print messages when VT is switched."); monitor = ck_vt_monitor_new (); res = ck_vt_monitor_get_active (monitor, &num, &error); if (! res) { g_warning ("Couldn't determine active VT: %s", error->message); exit (1); } g_message ("VT %u is currently active", num); g_signal_connect (monitor, "active-changed", G_CALLBACK (activated_cb), NULL); loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); g_object_unref (monitor); g_main_loop_unref (loop); return 0; } consolekit2-1.2.6/src/valgrind.sh000077500000000000000000000010721446640754400167260ustar00rootroot00000000000000#!/bin/sh export G_DEBUG=gc-friendly export G_SLICE=always-malloc,debug-blocks #valgrind --tool=massif --depth=5 --alloc-fn=g_malloc \ # --alloc-fn=g_realloc --alloc-fn=g_try_malloc \ # --alloc-fn=g_malloc0 --alloc-fn=g_mem_chunk_alloc \ # --log-file=/var/log/ck2-valgrind-massif.log \ # console-kit-daemon valgrind --tool=memcheck --leak-check=full --show-reachable=yes \ --leak-resolution=high --num-callers=500 \ --track-origins=yes --read-var-info=yes \ --show-leak-kinds=all --log-file=/var/log/ck2-valgrind-memcheck.log \ console-kit-daemon consolekit2-1.2.6/tools/000077500000000000000000000000001446640754400151325ustar00rootroot00000000000000consolekit2-1.2.6/tools/.gitignore000066400000000000000000000003531446640754400171230ustar00rootroot00000000000000*.la *.lo *.o .deps .libs Makefile Makefile.in ck-collect-session-info ck-get-x11-display-device ck-get-x11-server-pid ck-history ck-launch-session ck-list-sessions ck-log-system-start ck-log-system-restart ck-log-system-stop udev-acl consolekit2-1.2.6/tools/70-udev-acl.rules.in000066400000000000000000000056271446640754400205510ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update # taken/updated from: # https://github.com/systemd/systemd/blob/master/src/login/70-uaccess.rules # Do not use TAG+="udev-acl" outside of this file. This variable is private to # udev-acl of this udev release and may be replaced at any time. ENV{MAJOR}=="", GOTO="acl_end" ACTION=="remove", GOTO="acl_apply" # systemd replaces udev-acl entirely, skip if active TEST=="/sys/fs/cgroup/systemd", TAG=="uaccess", GOTO="acl_end" # PTP/MTP protocol devices, cameras, portable media players SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="udev-acl" # digicams with proprietary protocol ENV{ID_GPHOTO2}=="*?", TAG+="udev-acl" # SCSI and USB scanners ENV{libsane_matched}=="yes", TAG+="udev-acl" # HPLIP devices (necessary for ink level check and HP tool maintenance) ENV{ID_HPLIP}=="1", TAG+="udev-acl" # optical drives SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="udev-acl" SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="udev-acl" # sound devices SUBSYSTEM=="sound", TAG+="udev-acl" OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq" # ffado is an userspace driver for firewire sound cards SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="udev-acl" # webcams, frame grabber, TV cards SUBSYSTEM=="video4linux", TAG+="udev-acl" SUBSYSTEM=="dvb", TAG+="udev-acl" # IIDC devices: industrial cameras and some webcams SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", TAG+="udev-acl" SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="udev-acl" # AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="udev-acl" SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="udev-acl" # DRI video devices SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="udev-acl" SUBSYSTEM=="graphics", KERNEL=="fb*", TAG+="udev-acl" # KVM SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="udev-acl" # smart-card readers ENV{ID_SMARTCARD_READER}=="*?", TAG+="udev-acl" # (USB) authentication devices ENV{ID_SECURITY_TOKEN}=="?*", TAG+="udev-acl" # PDA devices ENV{ID_PDA}=="*?", TAG+="udev-acl" # Programmable remote control ENV{ID_REMOTE_CONTROL}=="1", TAG+="udev-acl" # joysticks SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="udev-acl" # color measurement devices ENV{COLOR_MEASUREMENT_DEVICE}=="*?", TAG+="udev-acl" # DDC/CI device, usually high-end monitors such as the DreamColor ENV{DDC_DEVICE}=="*?", TAG+="udev-acl" # media player raw devices (for user-mode drivers, Android SDK, etc.) SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="udev-acl" # software-defined radio communication devices ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="udev-acl" # apply ACL for all locally logged in users LABEL="acl_apply", TAG=="udev-acl", TEST=="@RUNDIR@/ConsoleKit/database", \ RUN+="udev-acl --action=$env{ACTION} --device=$env{DEVNAME}" LABEL="acl_end" consolekit2-1.2.6/tools/71-udev-seat.rules.in000066400000000000000000000046711446640754400207450ustar00rootroot00000000000000# do not edit this file, it will be overwritten on update # taken/updated from: # https://github.com/systemd/systemd/blob/master/src/login/71-seat.rules.in ACTION=="remove", GOTO="seat_end" TAG=="udev-acl", SUBSYSTEM!="sound", TAG+="seat" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat" SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat" SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat", TAG+="master-of-seat" SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat" SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat" # 'Plugable' USB hub, sound, network, graphics adapter SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="000[13]", ENV{ID_AUTOSEAT}="1" # qemu (version 2.4+) has a PCI-PCI bridge (-device pci-bridge-seat) to group # devices belonging to one seat. See: # http://git.qemu.org/?p=qemu.git;a=blob;f=docs/multiseat.txt SUBSYSTEM=="pci", ATTR{vendor}=="0x1b36", ATTR{device}=="0x000a", TAG+="seat", ENV{ID_AUTOSEAT}="1" # Mimo 720, with integrated USB hub, displaylink graphics, and e2i # touchscreen. This device carries no proper VID/PID in the USB hub, # but it does carry good ID data in the graphics component, hence we # check it from the parent. There's a bit of a race here however, # given that the child devices might not exist yet at the time this # rule is executed. To work around this we'll trigger the parent from # the child if we notice that the parent wasn't recognized yet. # Match parent SUBSYSTEM=="usb", ATTR{idVendor}=="058f", ATTR{idProduct}=="6254", \ ATTR{%k.2/idVendor}=="17e9", ATTR{%k.2/idProduct}=="401a", ATTR{%k.2/product}=="mimo inc", \ ENV{ID_AUTOSEAT}="1", ENV{ID_AVOID_LOOP}="1" # Match child, look for parent's ID_AVOID_LOOP SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \ ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \ IMPORT{parent}="ID_AVOID_LOOP" # Match child, retrigger parent SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \ ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \ ENV{ID_AVOID_LOOP}=="", \ RUN+="@rootbindir@/udevadm trigger --parent-match=%p/.." TAG=="seat", ENV{ID_PATH}=="", IMPORT{builtin}="path_id" TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}" LABEL="seat_end" consolekit2-1.2.6/tools/Makefile.am000066400000000000000000000101171446640754400171660ustar00rootroot00000000000000## We require new-style dependency handling. AUTOMAKE_OPTIONS = 1.7 NULL = SUBDIRS = \ $(NULL) if CK_COMPILE_LINUX SUBDIRS += linux endif if CK_COMPILE_FREEBSD SUBDIRS += freebsd endif if CK_COMPILE_NETBSD SUBDIRS += netbsd endif if CK_COMPILE_OPENBSD SUBDIRS += openbsd endif if CK_COMPILE_SOLARIS SUBDIRS += solaris endif DIST_SUBDIRS = \ linux \ freebsd \ netbsd \ openbsd \ solaris \ $(NULL) AM_CFLAGS = \ -I. \ -I$(srcdir) \ -I$(top_srcdir)/src \ -I$(top_srcdir)/libck-connector \ $(GLIB_CFLAGS) \ $(GIO_CFLAGS) \ $(GIO_UNIX_CFLAGS) \ $(POLKIT_CFLAGS) \ $(LIBDBUS_CFLAGS) \ $(CGMANAGER_CFLAGS) \ $(LIBUDEV_CFLAGS) \ $(LIBDRM_CFLAGS) \ $(SELINUX_CFLAGS) \ $(LIBEVDEV_CFLAGS) \ $(RBAC_CFLAGS) \ $(LIBX11_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ -DPREFIX=\""$(prefix)"\" \ -DBINDIR=\""$(bindir)"\" \ -DLIBDIR=\""$(libdir)"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" \ -DDATADIR=\""$(datadir)"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DLOCALSTATEDIR=\""$(localstatedir)"\" \ -DRUNDIR=\""$(RUNDIR)"\" \ -DLOCALEDIR=\"$(localedir)\" \ $(NULL) CONSOLE_KIT_LIBS = \ $(CK2_LIBS) \ $(TOOLS_LIBS) \ $(GLIB_LIBS) \ $(GIO_LIBS) \ $(GIO_UNIX_LIBS) \ $(LIBDBUS_LIBS) \ $(SELINUX_LIBS) \ $(LIBEVDEV_LIBS) \ $(POLKIT_LIBS) \ $(RBAC_LIBS) \ $(CGMANAGER_LIBS) \ $(LIBUDEV_LIBS) \ $(LIBDRM_LIBS) \ $(LIBX11_LIBS) bin_PROGRAMS = \ ck-launch-session \ ck-list-sessions \ ck-history \ $(NULL) sbin_PROGRAMS = \ ck-log-system-start \ ck-log-system-restart \ ck-log-system-stop \ $(NULL) ck_launch_session_SOURCES = \ ck-launch-session.c \ $(NULL) ck_launch_session_LDADD = \ $(top_builddir)/libck-connector/libck-connector.la \ $(CONSOLE_KIT_LIBS) \ $(NULL) ck_list_sessions_SOURCES = \ list-sessions.c \ $(NULL) ck_list_sessions_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(XLIB_LIBS) \ $(NULL) ck_history_SOURCES = \ ck-history.c \ $(NULL) ck_history_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(Z_LIBS) \ $(top_builddir)/src/libck-event-log.la \ $(NULL) ck_log_system_start_SOURCES = \ ck-log-system-start.c \ $(NULL) ck_log_system_start_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(top_builddir)/src/libck-event-log.la \ $(NULL) ck_log_system_restart_SOURCES = \ ck-log-system-restart.c \ $(NULL) ck_log_system_restart_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(top_builddir)/src/libck-event-log.la \ $(NULL) ck_log_system_stop_SOURCES = \ ck-log-system-stop.c \ $(NULL) ck_log_system_stop_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(top_builddir)/src/libck-event-log.la \ $(NULL) libexec_PROGRAMS = \ ck-collect-session-info \ ck-get-x11-server-pid \ ck-get-x11-display-device \ ck-remove-directory \ $(NULL) ck_collect_session_info_SOURCES = \ ck-collect-session-info.c \ $(NULL) ck_collect_session_info_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(top_builddir)/src/libck.la \ $(NULL) ck_get_x11_server_pid_SOURCES = \ ck-get-x11-server-pid.c \ $(NULL) ck_get_x11_server_pid_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(XLIB_LIBS) \ $(top_builddir)/src/libck.la \ $(NULL) ck_get_x11_display_device_SOURCES = \ ck-get-x11-display-device.c \ $(NULL) ck_get_x11_display_device_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(top_builddir)/src/libck.la \ $(NULL) ck_remove_directory_SOURCES = \ ck-remove-directory.c \ $(NULL) ck_remove_directory_LDADD = \ $(CONSOLE_KIT_LIBS) \ $(top_builddir)/src/libck.la \ $(NULL) if ENABLE_UDEV_ACL udevrulesdir = $(UDEVDIR)/rules.d dist_udevrules_DATA = \ 70-udev-acl.rules \ 71-udev-seat.rules libexec_PROGRAMS += udev-acl udev_acl_SOURCES = udev-acl.c udev_acl_LDADD = $(UDEV_ACL_LIBS) udev_acl_CFLAGS = \ $(UDEV_ACL_CFLAGS) \ $(AM_CFLAGS) \ $(NULL) install-exec-hook: mkdir -p $(DESTDIR)$(libdir)/ConsoleKit/run-seat.d mkdir -p $(DESTDIR)$(UDEVDIR) ln -sf $(libexecdir)/udev-acl $(DESTDIR)$(libdir)/ConsoleKit/run-seat.d/udev-acl.ck ln -sf $(libexecdir)/udev-acl $(DESTDIR)$(UDEVDIR)/udev-acl endif EXTRA_DIST = \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in consolekit2-1.2.6/tools/ck-collect-session-info.c000066400000000000000000000343761446640754400217450ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Authors: William Jon McCann * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-sysdeps.h" typedef struct { uid_t uid; pid_t pid; char *login_session_id; guint vtnum; char *display_device; char *x11_display_device; char *x11_display; gboolean x11_can_connect; char *remote_host_name; gboolean is_local; gboolean is_local_is_set; } SessionInfo; static void session_info_free (SessionInfo *si) { g_free (si->login_session_id); g_free (si->display_device); g_free (si->x11_display_device); g_free (si->x11_display); g_free (si->remote_host_name); g_free (si); } static void setuid_child_setup_func (SessionInfo *si) { int res; struct passwd *pwent; errno = 0; pwent = getpwuid (si->uid); if (pwent == NULL) { g_warning ("Unable to lookup UID: %s", g_strerror (errno)); exit (1); } /* set the group */ errno = 0; res = setgid (pwent->pw_gid); if (res == -1) { g_warning ("Error performing setgid: %s", g_strerror (errno)); exit (1); } /* become the user */ errno = 0; res = setuid (si->uid); if (res == -1) { g_warning ("Error performing setuid: %s", g_strerror (errno)); exit (1); } } static GPtrArray * get_filtered_environment (pid_t pid) { GPtrArray *env; GHashTable *hash; guint i; static const char *allowed_env_vars [] = { "DISPLAY", "XAUTHORITY", "XAUTHLOCALHOSTNAME", "SSH_CLIENT", "SSH_CONNECTION", "SSH_TTY", "HOME", }; env = g_ptr_array_new (); g_ptr_array_add (env, g_strdup ("PATH=/bin:/usr/bin")); hash = ck_unix_pid_get_env_hash (pid); for (i = 0; i < G_N_ELEMENTS (allowed_env_vars); i++) { const char *var; const char *val; var = allowed_env_vars [i]; val = g_hash_table_lookup (hash, var); if (val != NULL) { char *str; str = g_strdup_printf ("%s=%s", var, val); g_ptr_array_add (env, str); } } g_ptr_array_add (env, NULL); g_hash_table_destroy (hash); return env; } static void get_x11_server_pid (SessionInfo *si, gboolean *can_connect, guint *pid) { gboolean res; char *err; char *out; int status; guint i; GError *error; guint num; char *argv[4]; GPtrArray *env; if (can_connect != NULL) { *can_connect = FALSE; } if (pid != NULL) { *pid = 0; } /* get the applicable environment */ env = get_filtered_environment (si->pid); num = 0; argv[0] = LIBEXECDIR "/ck-get-x11-server-pid"; argv[1] = NULL; error = NULL; out = NULL; err = NULL; status = -1; res = g_spawn_sync (NULL, argv, (char **)env->pdata, 0, (GSpawnChildSetupFunc)setuid_child_setup_func, si, &out, &err, &status, &error); for (i = 0; i < env->len; i++) { g_free (g_ptr_array_index (env, i)); } g_ptr_array_free (env, TRUE); if (error != NULL) { g_warning ("Unable to PID for x11 server: %s", error->message); g_error_free (error); } if (status == 0) { if (res && out != NULL) { guint v; char c; if (1 == sscanf (out, "%u %c", &v, &c)) { num = v; } } if (can_connect != NULL) { *can_connect = TRUE; } } if (err != NULL && err[0] != '\0') { g_warning ("%s", err); } if (pid != NULL) { *pid = num; } g_free (out); g_free (err); } /* Looking at the XFree86_VT property on the root window * doesn't work very well because it is difficult to * distinguish local from remote systems and the value * can't necessarily be trusted. So instead we connect * to the server and use peer credentials to find the * local PID and then find its tty. */ static void fill_x11_info (SessionInfo *si) { guint xorg_pid; gboolean can_connect; gboolean res; CkProcessStat *xorg_stat; GError *error; char *err; char *out; int status; guint i; char *argv[4]; GPtrArray *env; /* assume this is true then check it */ si->x11_display = ck_unix_pid_get_env (si->pid, "DISPLAY"); if (si->x11_display == NULL) { /* no point continuing */ si->x11_can_connect = FALSE; return; } xorg_pid = 0; can_connect = FALSE; get_x11_server_pid (si, &can_connect, &xorg_pid); si->x11_can_connect = can_connect; if (! can_connect) { g_free (si->x11_display); si->x11_display = NULL; return; } if (xorg_pid < 2) { /* keep the tty value */ /* if we can connect but don't have a pid * then we're not local */ si->is_local = FALSE; si->is_local_is_set = TRUE; /* FIXME: get the remote hostname */ return; } error = NULL; res = ck_process_stat_new_for_unix_pid (xorg_pid, &xorg_stat, &error); if (! res) { if (error != NULL) { g_warning ("stat on pid %d failed: %s", xorg_pid, error->message); g_error_free (error); } /* keep the tty value */ return; } si->x11_display_device = ck_process_stat_get_tty (xorg_stat); if (g_strcmp0 (si->x11_display_device, si->display_device) != 0) { goto gotit; } g_free (si->x11_display_device); /* get the applicable environment */ env = get_filtered_environment (si->pid); argv[0] = LIBEXECDIR "/ck-get-x11-display-device"; argv[1] = NULL; error = NULL; out = NULL; err = NULL; status = -1; res = g_spawn_sync (NULL, argv, (char **)env->pdata, 0, (GSpawnChildSetupFunc)setuid_child_setup_func, si, &out, &err, &status, &error); for (i = 0; i < env->len; i++) { g_free (g_ptr_array_index (env, i)); } g_ptr_array_free (env, TRUE); if (error != NULL) { g_warning ("Unable to get display device for x11 server: %s", error->message); g_error_free (error); } if (status == 0) { if (res && out != NULL) { si->x11_display_device = g_strstrip (out); goto gotit; } } si->x11_display_device = ck_process_stat_get_tty (xorg_stat); gotit: ck_process_stat_free (xorg_stat); /* when PAM is supported don't set is-local here - let the daemon do that */ #ifndef HAVE_PAM si->is_local = TRUE; si->is_local_is_set = TRUE; #endif g_free (si->remote_host_name); si->remote_host_name = NULL; } static guint get_vtnr (SessionInfo *si) { guint vtnr; const char *device = NULL; if (si->x11_display_device != NULL) { device = si->x11_display_device; } else if (si->display_device != NULL) { device = si->display_device; } if (device != NULL) { if (ck_get_console_num_from_device (device, &vtnr) == FALSE) { return 0; } return vtnr; } return 0; } static gboolean fill_session_info (SessionInfo *si) { CkProcessStat *stat; GError *error; gboolean res; error = NULL; res = ck_process_stat_new_for_unix_pid (si->pid, &stat, &error); if (! res) { if (error != NULL) { g_warning ("stat on pid %d failed: %s", si->pid, error->message); g_error_free (error); } return FALSE; } si->display_device = ck_process_stat_get_tty (stat); ck_process_stat_free (stat); if (si->x11_display_device == NULL) { /* If our DM set the display device we don't need to look * it up here */ fill_x11_info (si); } #ifndef HAVE_PAM if (! si->is_local_is_set) { /* FIXME: how should we set this? */ /* non x11 sessions must be local I guess */ si->is_local = TRUE; si->is_local_is_set = TRUE; } #endif res = ck_unix_pid_get_login_session_id (si->pid, &si->login_session_id); if (! res) { si->login_session_id = NULL; } si->vtnum = get_vtnr (si); return TRUE; } static void print_session_info (SessionInfo *si) { printf ("unix-user = %u\n", si->uid); printf ("vtnr = %u\n", si->vtnum); if (si->x11_display != NULL) { printf ("x11-display = %s\n", si->x11_display); } if (si->x11_display_device != NULL) { printf ("x11-display-device = %s\n", si->x11_display_device); } if (si->display_device != NULL) { printf ("display-device = %s\n", si->display_device); } if (si->remote_host_name != NULL) { printf ("remote-host-name = %s\n", si->remote_host_name); } if (si->is_local_is_set == TRUE) { printf ("is-local = %s\n", si->is_local ? "true" : "false"); } if (si->login_session_id != NULL) { printf ("login-session-id = %s\n", si->login_session_id); } } static gboolean collect_session_info (uid_t uid, pid_t pid, gchar *x11_display_device) { SessionInfo *si; gboolean ret; si = g_new0 (SessionInfo, 1); si->uid = uid; si->pid = pid; si->x11_display_device = x11_display_device; ret = fill_session_info (si); if (ret) { print_session_info (si); } session_info_free (si); return ret; } int main (int argc, char **argv) { GOptionContext *context; gboolean ret; GError *error; static int user_id = -1; static int process_id = -1; static gchar *x11_display_device = NULL; static GOptionEntry entries [] = { { "uid", 0, 0, G_OPTION_ARG_INT, &user_id, "User ID", NULL }, { "pid", 0, 0, G_OPTION_ARG_INT, &process_id, "Process ID", NULL }, { "x11-display-device", 0, 0, G_OPTION_ARG_STRING, &x11_display_device, "X11 display device", NULL }, { NULL } }; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif /* For now at least restrict this to root */ if (getuid () != 0) { g_warning (_("You must be root to run this program")); exit (1); } context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); error = NULL; ret = g_option_context_parse (context, &argc, &argv, &error); g_option_context_free (context); if (! ret) { g_warning ("%s", error->message); g_error_free (error); exit (1); } if (user_id < 0) { g_warning ("Invalid UID"); exit (1); } if (process_id < 2) { g_warning ("Invalid PID"); exit (1); } ret = collect_session_info (user_id, process_id, x11_display_device); return ret != TRUE; } consolekit2-1.2.6/tools/ck-get-x11-display-device.c000066400000000000000000000176011446640754400217640ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Authors: William Jon McCann * */ #include "config.h" #include #include #include #include #ifdef HAVE_KVM_H #include #endif #ifdef HAVE_SYS_QUEUE_H #include #endif #ifdef HAVE_SYS_FCNTL_H #include #endif #ifdef HAVE_SYS_USER_H #include #endif #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef HAVE_SYS_SYSCTL_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_LIMITS_H #include #endif #include #include #include #include #include "ck-sysdeps.h" #ifdef __FreeBSD__ #include static char * get_tty_for_pid (int pid) { gchar *device = NULL; gboolean res; char errstr[_POSIX2_LINE_MAX]; int cnt = 0; struct vnstat vn; struct filestat_list *head; struct filestat *fst; kvm_t* kd; struct kinfo_proc * prc; struct procstat *procstat; kd = kvm_openfiles (NULL, "/dev/null", NULL, O_RDONLY, errstr); prc = kvm_getprocs (kd, KERN_PROC_PID, pid, &cnt); procstat = procstat_open_sysctl (); for (int i = 0; i < cnt; i++) { head = procstat_getfiles (procstat,&prc[i], 0); STAILQ_FOREACH (fst, head, next) { if (fst->fs_type == PS_FST_TYPE_VNODE) { procstat_get_vnode_info (procstat, fst, &vn, NULL); if (vn.vn_type == PS_FST_VTYPE_VCHR) { char *ctty = devname( prc[i].ki_tdev,S_IFCHR); const char * pre = "ttyv"; if(strncmp (pre, vn.vn_devname, strlen (pre)) == 0 && strncmp (vn.vn_devname, ctty, strlen(ctty)) != 0) { device = g_strdup_printf ("/dev/%s", vn.vn_devname); procstat_freefiles (procstat, head); res = TRUE; return device; } } } } } procstat_freefiles(procstat, head); return device; } #else /* __FreeBSD__ */ static char * get_tty_for_pid (int pid) { GError *error; char *device; gboolean res; CkProcessStat *xorg_stat; error = NULL; res = ck_process_stat_new_for_unix_pid (pid, &xorg_stat, &error); if (! res) { if (error != NULL) { g_warning ("stat on pid %d failed: %s", pid, error->message); g_error_free (error); } /* keep the tty value */ return NULL; } device = ck_process_stat_get_tty (xorg_stat); ck_process_stat_free (xorg_stat); return device; } #endif /* __FreeBSD__ */ static Display * display_init (const char *display_name) { Display *xdisplay; if (display_name == NULL) { display_name = g_getenv ("DISPLAY"); } if (display_name == NULL) { g_warning ("DISPLAY is not set"); exit (1); } xdisplay = XOpenDisplay (display_name); if (xdisplay == NULL) { g_warning ("cannot open display: %s", display_name ? display_name : ""); exit (1); } return xdisplay; } static char * get_tty_for_display (Display *xdisplay) { Window root_window; Atom xfree86_vt_atom; Atom return_type_atom; int return_format; gulong return_count; gulong bytes_left; guchar *return_value; glong vt; char *display; display = NULL; xfree86_vt_atom = XInternAtom (xdisplay, "XFree86_VT", True); if (xfree86_vt_atom == None) { return NULL; } root_window = DefaultRootWindow (xdisplay); g_assert (root_window != None); return_value = NULL; if (XGetWindowProperty(xdisplay, root_window, xfree86_vt_atom, 0L, 1L, False, XA_INTEGER, &return_type_atom, &return_format, &return_count, &bytes_left, &return_value) != Success) { goto out; } if (return_type_atom != XA_INTEGER) { goto out; } if (return_format != 32) { goto out; } if (return_count != 1) { goto out; } if (bytes_left != 0) { goto out; } memcpy(&vt, return_value, sizeof(glong)); if (vt <= 0) { goto out; } #if defined(__NetBSD__) display = g_strdup_printf ("/dev/ttyE%ld", vt - 1); #elif defined(__FreeBSD__) display = g_strdup_printf ("/dev/ttyv%ld", vt - 1); #elif defined(__OpenBSD__) display = g_strdup_printf ("/dev/ttyC%ld", vt - 1); #else display = g_strdup_printf ("/dev/tty%ld", vt); #endif out: if (return_value != NULL) { XFree (return_value); } return display; } int main (int argc, char **argv) { int fd; int ret; Display *xdisplay; static char *display = NULL; GError *error; GOptionContext *context; static GOptionEntry entries [] = { { "display", 0, 0, G_OPTION_ARG_STRING, &display, N_("display name"), NULL }, { NULL } }; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif ret = 1; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); error = NULL; ret = g_option_context_parse (context, &argc, &argv, &error); g_option_context_free (context); xdisplay = display_init (display); fd = ConnectionNumber (xdisplay); if (fd > 0) { int pid; char *device; gboolean res; ret = 0; res = ck_get_socket_peer_credentials (fd, &pid, NULL, NULL); if (res) { if (pid > 0) { device = get_tty_for_pid (pid); if (device == NULL) { device = get_tty_for_display (xdisplay); } if (device != NULL) { printf ("%s\n", device); g_free (device); } } } } return ret; } consolekit2-1.2.6/tools/ck-get-x11-server-pid.c000066400000000000000000000051111446640754400211330ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Authors: William Jon McCann * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "ck-sysdeps.h" static Display * display_init (int *argc, char ***argv) { const char *display_name; Display *xdisplay; display_name = g_getenv ("DISPLAY"); if (display_name == NULL) { g_warning ("DISPLAY is not set"); exit (1); } if (display_name[0] != ':' && g_strrstr(display_name, ":") != NULL) { g_warning ("DISPLAY is not a UNIX domain socket, can't get PID"); exit (1); } xdisplay = XOpenDisplay (display_name); if (xdisplay == NULL) { g_warning ("cannot open display: %s", display_name ? display_name : ""); exit (1); } return xdisplay; } int main (int argc, char **argv) { int fd; int ret; Display *xdisplay; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif ret = 1; xdisplay = display_init (&argc, &argv); fd = ConnectionNumber (xdisplay); if (fd > 0) { int pid; gboolean res; ret = 0; res = ck_get_socket_peer_credentials (fd, &pid, NULL, NULL); if (res) { if (pid > 0) { printf ("%d\n", pid); } } } return ret; } consolekit2-1.2.6/tools/ck-history.c000066400000000000000000000740661446640754400174070ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2007 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-log-event.h" typedef enum { REPORT_TYPE_SUMMARY = 0, REPORT_TYPE_LAST, REPORT_TYPE_LAST_COMPAT, REPORT_TYPE_FREQUENT, REPORT_TYPE_LOG, } ReportType; /* same record types as sysvinit last */ typedef enum { RECORD_STATUS_CRASH = 1, /* No logout record, system boot in between */ RECORD_STATUS_DOWN, /* System brought down in decent way */ RECORD_STATUS_NORMAL, /* Normal */ RECORD_STATUS_NOW, /* Still logged in */ RECORD_STATUS_REBOOT, /* Reboot record. */ RECORD_STATUS_PHANTOM, /* No logout record but session is stale. */ RECORD_STATUS_TIMECHANGE, /* NEW_TIME or OLD_TIME */ } RecordStatus; #define DEFAULT_LOG_FILENAME LOCALSTATEDIR "/log/ConsoleKit/history" #define MAX_LINE_LEN 2048 #define USERNAME_MAX "24" static GList *all_events = NULL; static CkLogEvent * parse_event_line (const char *line) { GString *str; CkLogEvent *event; str = g_string_new (line); event = ck_log_event_new_from_string (str); g_string_free (str, TRUE); return event; } static gboolean process_log_gzstream (gzFile fstream, GTimeVal *since) { char line[MAX_LINE_LEN]; gboolean hit_since; GList *events; events = NULL; hit_since = FALSE; while (gzgets (fstream, line, sizeof (line)) != Z_NULL) { CkLogEvent *event; if (strlen (line) == sizeof (line) - 1) { g_warning ("Log line truncated"); } event = parse_event_line (line); if (event == NULL) { continue; } if (since == NULL || event->timestamp.tv_sec >= since->tv_sec) { events = g_list_prepend (events, event); } else { hit_since = TRUE; } } all_events = g_list_concat (all_events, events); return !hit_since; } static gboolean process_log_stream (FILE *fstream, GTimeVal *since) { char line[MAX_LINE_LEN]; gboolean hit_since; GList *events; events = NULL; hit_since = FALSE; while (fgets (line, sizeof (line), fstream) != NULL) { CkLogEvent *event; if (strlen (line) == sizeof (line) - 1) { g_warning ("Log line truncated"); } event = parse_event_line (line); if (event == NULL) { continue; } if (since == NULL || event->timestamp.tv_sec >= since->tv_sec) { events = g_list_prepend (events, event); } else { hit_since = TRUE; } } all_events = g_list_concat (all_events, events); return !hit_since; } static gboolean process_log_file (const char *filename, GTimeVal *since) { gboolean ret; if (g_str_has_suffix (filename, ".gz")) { gzFile f; f = gzopen (filename, "r"); if (f == NULL) { int errnum; const char *errmsg; errmsg = gzerror (f, &errnum); if (errnum == Z_ERRNO) { errmsg = g_strerror (errno); } g_warning ("Error opening %s (%s)\n", filename, errmsg); return FALSE; } ret = process_log_gzstream (f, since); gzclose (f); } else { FILE *f; f = g_fopen (filename, "r"); if (f == NULL) { g_warning ("Error opening %s (%s)\n", filename, g_strerror (errno)); return FALSE; } ret = process_log_stream (f, since); fclose (f); } return ret; } static GList * get_log_file_list (void) { int num; GList *files; /* always try the primary file */ files = NULL; files = g_list_prepend (files, g_strdup (DEFAULT_LOG_FILENAME)); num = 1; while (1) { char *filename; filename = g_strdup_printf ("%s.%d", DEFAULT_LOG_FILENAME, num); if (g_access (filename, R_OK) != 0) { char *filename_gz; /* check for .gz */ filename_gz = g_strdup_printf ("%s.gz", filename); g_free (filename); if (g_access (filename_gz, R_OK) != 0) { g_free (filename_gz); break; } filename = filename_gz; } num++; files = g_list_prepend (files, filename); }; /* Return the list in reverse time order, newest first */ files = g_list_reverse (files); return files; } static gboolean process_logs (GTimeVal *since) { gboolean ret; GList *files; GList *l; ret = FALSE; files = get_log_file_list (); for (l = files; l != NULL; l = l->next) { gboolean res; char *filename; filename = l->data; res = process_log_file (filename, since); if (! res) { goto out; } } ret = TRUE; out: g_list_foreach (files, (GFunc)g_free, NULL); g_list_free (files); return ret; } static void generate_report_summary (int uid, const char *seat, const char *session_type) { } static CkLogEvent * find_first_matching_remove_event (GList *events, CkLogSeatSessionAddedEvent *event) { CkLogEvent *revent; GList *l; revent = NULL; for (l = events; l != NULL; l = l->next) { CkLogEventType etype; etype = ((CkLogEvent *)l->data)->type; /* skip all non removal events */ if (! (etype == CK_LOG_EVENT_SEAT_SESSION_REMOVED || etype == CK_LOG_EVENT_SYSTEM_START || etype == CK_LOG_EVENT_SYSTEM_STOP || etype == CK_LOG_EVENT_SYSTEM_RESTART)) { continue; } if (etype == CK_LOG_EVENT_SEAT_SESSION_REMOVED) { CkLogSeatSessionRemovedEvent *e; e = l->data; if (e->session_id != NULL && event->session_id != NULL && strcmp (e->session_id, event->session_id) == 0) { revent = (CkLogEvent *)l->data; break; } } else { revent = (CkLogEvent *)l->data; break; } } return revent; } static CkLogEvent * find_first_matching_system_stop_event (GList *events, CkLogSeatSessionAddedEvent *event) { CkLogEvent *revent; GList *l; revent = NULL; for (l = events; l != NULL; l = l->next) { CkLogEventType etype; etype = ((CkLogEvent *)l->data)->type; /* skip all non removal events */ if (! (etype == CK_LOG_EVENT_SYSTEM_STOP || etype == CK_LOG_EVENT_SYSTEM_RESTART)) { continue; } revent = (CkLogEvent *)l->data; break; } return revent; } static char * get_user_name_for_uid (int uid) { struct passwd *pwent; char *name; name = NULL; pwent = getpwuid (uid); if (pwent != NULL) { name = g_strdup (pwent->pw_name); } return name; } static int get_uid_for_username (const char *username) { struct passwd *pwent; int uid; g_assert (username != NULL); uid = -1; pwent = getpwnam (username); if (pwent != NULL) { uid = pwent->pw_uid; } return uid; } static char * get_utline_for_event (CkLogEvent *event) { char *utline; utline = NULL; switch (event->type) { case CK_LOG_EVENT_SEAT_SESSION_ADDED: { CkLogSeatSessionAddedEvent *e; e = (CkLogSeatSessionAddedEvent *)event; if (e->session_x11_display_device != NULL && e->session_x11_display_device[0] != '\0') { if (g_str_has_prefix (e->session_x11_display_device, "/dev/")) { utline = g_strdup (e->session_x11_display_device + 5); } else { utline = g_strdup (e->session_x11_display_device); } } else { if (g_str_has_prefix (e->session_display_device, "/dev/")) { utline = g_strdup (e->session_display_device + 5); } else { utline = g_strdup (e->session_display_device); } } } break; case CK_LOG_EVENT_SYSTEM_START: utline = g_strdup ("system boot"); break; default: g_assert_not_reached (); } return utline; } static char * get_user_name_for_event (CkLogEvent *event) { char *username; username = NULL; switch (event->type) { case CK_LOG_EVENT_SEAT_SESSION_ADDED: username = get_user_name_for_uid (((CkLogSeatSessionAddedEvent *)event)->session_unix_user); break; case CK_LOG_EVENT_SYSTEM_START: username = g_strdup ("reboot"); break; default: g_assert_not_reached (); } return username; } static char * get_host_for_event (CkLogEvent *event) { char *name; name = NULL; switch (event->type) { case CK_LOG_EVENT_SEAT_SESSION_ADDED: name = g_strdup (((CkLogSeatSessionAddedEvent *)event)->session_remote_host_name); if (name == NULL) { /* If not set then use the display value */ name = g_strdup (((CkLogSeatSessionAddedEvent *)event)->session_x11_display); } break; case CK_LOG_EVENT_SYSTEM_START: name = g_strdup (((CkLogSystemStartEvent *)event)->kernel_release); break; default: g_assert_not_reached (); } return name; } static RecordStatus get_event_record_status (CkLogEvent *remove_event) { RecordStatus status; status = RECORD_STATUS_NOW; if (remove_event == NULL) { goto out; } if (remove_event->type == CK_LOG_EVENT_SEAT_SESSION_REMOVED) { status = RECORD_STATUS_NORMAL; } else if (remove_event->type == CK_LOG_EVENT_SYSTEM_START) { status = RECORD_STATUS_CRASH; } else if (remove_event->type == CK_LOG_EVENT_SYSTEM_STOP) { status = RECORD_STATUS_DOWN; } else if (remove_event->type == CK_LOG_EVENT_SYSTEM_RESTART) { status = RECORD_STATUS_DOWN; } out: return status; } static char * get_duration (CkLogEvent *event, CkLogEvent *remove_event) { time_t secs; int mins; int hours; int days; char *duration; if (remove_event != NULL) { secs = remove_event->timestamp.tv_sec - event->timestamp.tv_sec; } else { GTimeVal now; g_get_current_time (&now); secs = now.tv_sec - event->timestamp.tv_sec; } mins = (secs / 60) % 60; hours = (secs / 3600) % 24; days = secs / 86400; if (days > 0) { duration = g_strdup_printf ("(%d+%02d:%02d)", days, hours, mins); } else { duration = g_strdup_printf (" (%02d:%02d)", hours, mins); } return duration; } static void print_last_report_record (GList *list, CkLogEvent *event, gboolean legacy_compat) { GString *str; char *username; char *utline; char *host; char *addedtime; char *removedtime; char *duration; char *session_type; char *session_id; char *seat_id; CkLogSeatSessionAddedEvent *e = NULL; CkLogEvent *remove_event; RecordStatus status; time_t added_t, removed_t; if (event->type != CK_LOG_EVENT_SEAT_SESSION_ADDED && event->type != CK_LOG_EVENT_SYSTEM_START) { return; } remove_event = NULL; if (event->type == CK_LOG_EVENT_SEAT_SESSION_ADDED) { e = (CkLogSeatSessionAddedEvent *)event; remove_event = find_first_matching_remove_event (list->next, e); status = get_event_record_status (remove_event); session_type = e->session_type; session_id = e->session_id; seat_id = e->seat_id; } else { status = RECORD_STATUS_REBOOT; remove_event = find_first_matching_system_stop_event (list->next, NULL); session_type = ""; session_id = ""; seat_id = ""; } str = g_string_new (NULL); username = get_user_name_for_event (event); utline = get_utline_for_event (event); host = get_host_for_event (event); added_t = event->timestamp.tv_sec; addedtime = g_strndup (ctime (&added_t), 16); if (legacy_compat) { g_string_printf (str, "%-8.8s %-12.12s %-16.16s %-16.16s", username, utline != NULL ? utline : "", host != NULL ? host : "", addedtime); } else { g_string_printf (str, "%-"USERNAME_MAX"."USERNAME_MAX"s %12s %-10.10s %-7.7s %-12.12s %-28.28s %-16.16s", username, session_type, session_id, seat_id, utline, host != NULL ? host : "", addedtime); } g_free (username); g_free (addedtime); g_free (utline); g_free (host); removedtime = NULL; duration = NULL; switch (status) { case RECORD_STATUS_CRASH: duration = get_duration (event, remove_event); removedtime = g_strdup ("- crash"); break; case RECORD_STATUS_DOWN: duration = get_duration (event, remove_event); removedtime = g_strdup ("- down "); break; case RECORD_STATUS_NOW: duration = g_strdup ("logged in"); removedtime = g_strdup (" still"); break; case RECORD_STATUS_PHANTOM: duration = g_strdup ("- no logout"); removedtime = g_strdup (" gone"); break; case RECORD_STATUS_REBOOT: duration = get_duration (event, remove_event); removedtime = g_strdup (""); break; case RECORD_STATUS_TIMECHANGE: duration = g_strdup (""); removedtime = g_strdup (""); break; case RECORD_STATUS_NORMAL: duration = get_duration (event, remove_event); removed_t = remove_event->timestamp.tv_sec; removedtime = g_strdup_printf ("- %s", ctime (&removed_t) + 11); removedtime[7] = 0; break; default: g_assert_not_reached (); break; } g_string_append_printf (str, " %-7.7s %-12.12s", removedtime, duration); g_print ("%s\n", str->str); g_string_free (str, TRUE); g_free (removedtime); g_free (duration); } static void generate_report_last (int uid, const char *seat, const char *session_type) { GList *oldest; CkLogEvent *oldest_event; GList *l; time_t oldest_e; /* print events in reverse time order */ for (l = g_list_last (all_events); l != NULL; l = l->prev) { CkLogEvent *event; event = l->data; if (event->type == CK_LOG_EVENT_SEAT_SESSION_ADDED) { CkLogSeatSessionAddedEvent *e; e = (CkLogSeatSessionAddedEvent *)event; if (uid >= 0 && e->session_unix_user != (guint)uid) { continue; } if (seat != NULL && e->seat_id != NULL && strcmp (e->seat_id, seat) != 0) { continue; } if (session_type != NULL && e->session_type != NULL && strcmp (e->session_type, session_type) != 0) { continue; } } print_last_report_record (l, event, FALSE); } oldest = g_list_first (all_events); if (oldest != NULL) { oldest_event = oldest->data; oldest_e = oldest_event->timestamp.tv_sec; g_print ("\nLog begins %s", ctime (&oldest_e)); } } static void generate_report_last_compat (int uid, const char *seat, const char *session_type) { GList *oldest; CkLogEvent *oldest_event; GList *l; time_t oldest_e; /* print events in reverse time order */ for (l = g_list_last (all_events); l != NULL; l = l->prev) { CkLogEvent *event; event = l->data; if (event->type == CK_LOG_EVENT_SEAT_SESSION_ADDED) { CkLogSeatSessionAddedEvent *e; e = (CkLogSeatSessionAddedEvent *)event; if (uid >= 0 && e->session_unix_user != (guint)uid) { continue; } if (seat != NULL && e->seat_id != NULL && strcmp (e->seat_id, seat) != 0) { continue; } if (session_type != NULL && e->session_type != NULL && strcmp (e->session_type, session_type) != 0) { continue; } } print_last_report_record (l, event, TRUE); } oldest = g_list_first (all_events); if (oldest != NULL) { oldest_event = oldest->data; oldest_e = oldest_event->timestamp.tv_sec; g_print ("\nLog begins %s", ctime (&oldest_e)); } } typedef struct { int uid; guint count; } CountData; static void listify_counts (gpointer key, gpointer val, GList **list) { CountData *count_data; count_data = g_new0 (CountData, 1); count_data->uid = GPOINTER_TO_INT (key); count_data->count = GPOINTER_TO_UINT (val); *list = g_list_prepend (*list, count_data); } static int counts_compare (CountData *a, CountData *b) { if (a->count < b->count) { return 1; } else if (a->count > b->count) { return -1; } else { return 0; } } static void generate_report_frequent (int uid, const char *seat, const char *session_type) { GHashTable *counts; GList *l; GList *user_counts; /* FIXME: we can probably do this more efficiently */ counts = g_hash_table_new (NULL, NULL); for (l = g_list_first (all_events); l != NULL; l = l->next) { CkLogEvent *event; CkLogSeatSessionAddedEvent *e; guint count; gpointer val; event = l->data; if (event->type != CK_LOG_EVENT_SEAT_SESSION_ADDED) { continue; } e = (CkLogSeatSessionAddedEvent *)event; if (uid >= 0 && e->session_unix_user != (guint)uid) { continue; } if (seat != NULL && e->seat_id != NULL && strcmp (e->seat_id, seat) != 0) { continue; } if (session_type != NULL && e->session_type != NULL && strcmp (e->session_type, session_type) != 0) { continue; } val = g_hash_table_lookup (counts, GINT_TO_POINTER (e->session_unix_user)); if (val != NULL) { count = GPOINTER_TO_INT (val); } else { count = 0; } g_hash_table_insert (counts, GINT_TO_POINTER (e->session_unix_user), GUINT_TO_POINTER (count + 1)); } user_counts = NULL; g_hash_table_foreach (counts, (GHFunc)listify_counts, &user_counts); g_hash_table_destroy (counts); if (user_counts == NULL) { return; } user_counts = g_list_sort (user_counts, (GCompareFunc)counts_compare); while (user_counts != NULL) { CountData *data; char *username; data = user_counts->data; username = get_user_name_for_uid (data->uid); g_print ("%-"USERNAME_MAX"s %u\n", username, data->count); g_free (data); user_counts = g_list_delete_link (user_counts, user_counts); g_free (username); } g_list_free (user_counts); } static void generate_report_log (int uid, const char *seat, const char *session_type) { GList *l; for (l = all_events; l != NULL; l = l->next) { CkLogEvent *event; GString *str; event = l->data; str = g_string_new (NULL); ck_log_event_to_string (event, str); g_print ("%s\n", str->str); g_string_free (str, TRUE); } } static void generate_report (int report_type, int uid, const char *seat, const char *session_type) { all_events = g_list_reverse (all_events); switch (report_type) { case REPORT_TYPE_SUMMARY: generate_report_summary (uid, seat, session_type); break; case REPORT_TYPE_LAST: generate_report_last (uid, seat, session_type); break; case REPORT_TYPE_LAST_COMPAT: generate_report_last_compat (uid, seat, session_type); break; case REPORT_TYPE_FREQUENT: generate_report_frequent (uid, seat, session_type); break; case REPORT_TYPE_LOG: generate_report_log (uid, seat, session_type); break; default: g_assert_not_reached (); break; } } static void free_events (void) { /* FIXME: */ } int main (int argc, char **argv) { GOptionContext *context; gboolean retval; GError *error = NULL; int report_type; int uid; GTimeVal timestamp; gboolean use_since; static gboolean do_version = FALSE; static gboolean report_last_compat = FALSE; static gboolean report_last = FALSE; static gboolean report_frequent = FALSE; static gboolean report_log = FALSE; static char *username = NULL; static char *seat = NULL; static char *session_type = NULL; static char *since = NULL; static GOptionEntry entries [] = { { "version", 'V', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL }, { "frequent", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &report_frequent, N_("Show listing of frequent users"), NULL }, { "last", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &report_last, N_("Show listing of last logged in users"), NULL }, { "last-compat", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &report_last_compat, N_("Show 'last' compatible listing of last logged in users"), NULL }, { "log", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &report_log, N_("Show full event log"), NULL }, { "seat", 's', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &seat, N_("Show entries for the specified seat"), N_("SEAT") }, { "session-type", 't', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &session_type, N_("Show entries for the specified session type"), N_("TYPE") }, { "user", 'u', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &username, N_("Show entries for the specified user"), N_("NAME") }, { "since", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &since, N_("Show entries since the specified time (ISO 8601 format)"), N_("DATETIME") }, { NULL } }; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); retval = g_option_context_parse (context, &argc, &argv, &error); g_option_context_free (context); if (! retval) { g_warning ("%s", error->message); g_error_free (error); exit (1); } if (do_version) { g_print ("%s %s\n", argv [0], VERSION); exit (1); } use_since = FALSE; if (since != NULL) { use_since = g_time_val_from_iso8601 (since, ×tamp); if (! use_since) { g_warning ("Invalid ISO 8601 time value"); exit (1); } } if (report_last_compat) { report_type = REPORT_TYPE_LAST_COMPAT; } else if (report_last) { report_type = REPORT_TYPE_LAST; } else if (report_frequent) { report_type = REPORT_TYPE_FREQUENT; } else if (report_log) { report_type = REPORT_TYPE_LOG; } else { report_type = REPORT_TYPE_SUMMARY; } if (username != NULL) { uid = get_uid_for_username (username); if (uid == -1) { g_warning ("Unknown username: %s", username); exit (1); } } else { uid = -1; } if (use_since) { process_logs (×tamp); } else { process_logs (NULL); } generate_report (report_type, uid, seat, session_type); free_events (); return 0; } consolekit2-1.2.6/tools/ck-launch-session.c000066400000000000000000000101631446640754400206250ustar00rootroot00000000000000/* * Copyright Red Hat, Inc. 2007-2008. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Red Hat, Inc., nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Gate a process inside of a ConsoleKit session. * */ #include #include #ifdef HAVE_PATHS_H #include #else #define _PATH_BSHELL "/bin/sh" #endif #include #include #include #include #include #include #include #include "ck-connector.h" static gboolean check_shell (const gchar *shell) { if (shell == NULL || *shell == '\0') { return FALSE; } if (!g_file_test (shell, G_FILE_TEST_IS_EXECUTABLE)) { return FALSE; } return TRUE; } int main (int argc, char **argv) { CkConnector *ckc = NULL; DBusError error; const char *shell; pid_t pid; int status; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif ckc = ck_connector_new (); if (ckc != NULL) { dbus_error_init (&error); if (ck_connector_open_session (ckc, &error)) { const char *runtime_dir = NULL; pid = fork (); switch (pid) { case -1: syslog (LOG_ERR, "error forking child"); break; case 0: setenv ("XDG_SESSION_COOKIE", ck_connector_get_cookie (ckc), 1); runtime_dir = ck_connector_get_runtime_dir (ckc, &error); if (runtime_dir != NULL) { setenv ("XDG_RUNTIME_DIR", runtime_dir, 1); } break; default: waitpid (pid, &status, 0); exit (status); break; } } else { syslog (LOG_ERR, "error connecting to ConsoleKit"); } } else { syslog (LOG_ERR, "error setting up to connection to ConsoleKit"); } if (argc > 1) { execvp (argv[1], argv + 1); } else { shell = getenv ("SHELL"); if (!check_shell (shell)) { shell = _PATH_BSHELL; } execlp (shell, shell, NULL); } _exit (1); } consolekit2-1.2.6/tools/ck-log-system-restart.c000066400000000000000000000116071446640754400214630ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-log-event.h" #define DEFAULT_LOG_FILENAME LOCALSTATEDIR "/log/ConsoleKit/history" /* Adapted from auditd auditd-event.c */ static gboolean open_log_file (const char *filename, int *fdp, FILE **filep) { int flags; int fd; FILE *file; gboolean ret; ret = FALSE; /* * Likely errors on rotate: ENFILE, ENOMEM, ENOSPC */ flags = O_WRONLY | O_APPEND; #ifdef O_NOFOLLOW flags |= O_NOFOLLOW; #endif retry: fd = g_open (filename, flags, 0600); if (fd < 0) { if (errno == ENOENT) { /* FIXME: should we just skip if file doesn't exist? */ fd = g_open (filename, O_CREAT | O_EXCL | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { g_warning ("Couldn't create log file %s (%s)", filename, g_strerror (errno)); goto out; } close (fd); fd = g_open (filename, flags, 0600); } else if (errno == ENFILE) { /* All system descriptors used, try again... */ goto retry; } if (fd < 0) { g_warning ("Couldn't open log file %s (%s)", filename, g_strerror (errno)); goto out; } } if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) { close (fd); g_warning ("Error setting log file CLOEXEC flag (%s)", g_strerror (errno)); goto out; } if (fchown (fd, 0, 0) == -1) { g_warning ("Error changing owner of log file (%s)", g_strerror (errno)); } file = fdopen (fd, "a"); if (file == NULL) { g_warning ("Error setting up log descriptor (%s)", g_strerror (errno)); close (fd); goto out; } /* Set it to line buffering */ setlinebuf (file); ret = TRUE; if (fdp != NULL) { *fdp = fd; } if (filep != NULL) { *filep = file; } out: return ret; } static gboolean write_log_for_event (CkLogEvent *event) { GString *str; FILE *file; int fd; str = g_string_new (NULL); ck_log_event_to_string (event, str); if (! open_log_file (DEFAULT_LOG_FILENAME, &fd, &file)) { exit (1); } if (file != NULL) { int rc; rc = fprintf (file, "%s\n", str->str); if (rc <= 0) { g_warning ("Record was not written to disk (%s)", g_strerror (errno)); } } else { g_warning ("Log file not open for writing"); } g_string_free (str, TRUE); return TRUE; } int main (int argc, char **argv) { CkLogEvent event; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SYSTEM_RESTART; g_get_current_time (&event.timestamp); write_log_for_event (&event); return 0; } consolekit2-1.2.6/tools/ck-log-system-start.c000066400000000000000000000160311446640754400211300ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #ifdef __FreeBSD__ #include #endif #include #include #include #include #include #include #include #include #include #include "ck-log-event.h" #define DEFAULT_LOG_FILENAME LOCALSTATEDIR "/log/ConsoleKit/history" #ifdef __linux__ #define LINUX_KERNEL_CMDLINE "/proc/cmdline" #endif /* Adapted from auditd auditd-event.c */ static gboolean open_log_file (const char *filename, int *fdp, FILE **filep) { int flags; int fd; int res; char *dirname; FILE *file; gboolean ret; ret = FALSE; /* * Likely errors on rotate: ENFILE, ENOMEM, ENOSPC */ flags = O_WRONLY | O_APPEND; #ifdef O_NOFOLLOW flags |= O_NOFOLLOW; #endif dirname = g_path_get_dirname (filename); /* always make sure we have a directory */ errno = 0; res = g_mkdir_with_parents (dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); if (res < 0) { g_warning ("Unable to create directory %s (%s)", dirname, g_strerror (errno)); g_free (dirname); return FALSE; } g_free (dirname); retry: fd = g_open (filename, flags, 0600); if (fd < 0) { if (errno == ENOENT) { /* FIXME: should we just skip if file doesn't exist? */ fd = g_open (filename, O_CREAT | O_EXCL | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { g_warning ("Couldn't create log file %s (%s)", filename, g_strerror (errno)); goto out; } close (fd); fd = g_open (filename, flags, 0600); } else if (errno == ENFILE) { /* All system descriptors used, try again... */ goto retry; } if (fd < 0) { g_warning ("Couldn't open log file %s (%s)", filename, g_strerror (errno)); goto out; } } if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) { close (fd); g_warning ("Error setting log file CLOEXEC flag (%s)", g_strerror (errno)); goto out; } if (fchown (fd, 0, 0) == -1) { g_warning ("Error changing owner of log file (%s)", g_strerror (errno)); } file = fdopen (fd, "a"); if (file == NULL) { g_warning ("Error setting up log descriptor (%s)", g_strerror (errno)); close (fd); goto out; } /* Set it to line buffering */ setlinebuf (file); ret = TRUE; if (fdp != NULL) { *fdp = fd; } if (filep != NULL) { *filep = file; } out: return ret; } static gboolean write_log_for_event (CkLogEvent *event) { GString *str; FILE *file; int fd; str = g_string_new (NULL); ck_log_event_to_string (event, str); if (! open_log_file (DEFAULT_LOG_FILENAME, &fd, &file)) { exit (1); } if (file != NULL) { int rc; rc = fprintf (file, "%s\n", str->str); if (rc <= 0) { g_warning ("Record was not written to disk (%s)", g_strerror (errno)); } } else { g_warning ("Log file not open for writing"); } g_string_free (str, TRUE); return TRUE; } static char * get_boot_arguments (void) { #if defined(__linux__) char *contents; gboolean res; contents = NULL; res = g_file_get_contents (LINUX_KERNEL_CMDLINE, &contents, NULL, NULL); if (!res) { g_free (contents); contents = NULL; } else { g_strchomp (contents); } return contents; #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) char kern_name[1024], root[1024], mopts[1024]; char *options; options = NULL; if (kenv(KENV_GET, "kernelname", kern_name, sizeof (kern_name)) == -1) { return options; } if (kenv(KENV_GET, "vfs.root.mountfrom.options", mopts, sizeof (mopts)) == -1) { g_strlcpy (mopts, "ro", sizeof (mopts)); } if (kenv(KENV_GET, "vfs.root.mountfrom", root, sizeof (root)) == -1) { g_strlcpy (root, "/", sizeof (root)); } options = g_strdup_printf ("%s %s root=%s", mopts, kern_name, root); return options; #else return NULL; #endif } int main (int argc, char **argv) { CkLogEvent event; CkLogSystemStartEvent *e; struct utsname uts; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SYSTEM_START; g_get_current_time (&event.timestamp); e = (CkLogSystemStartEvent *) &event.event; if (uname (&uts) == 0) { e->kernel_release = uts.release; } e->boot_arguments = get_boot_arguments (); write_log_for_event (&event); return 0; } consolekit2-1.2.6/tools/ck-log-system-stop.c000066400000000000000000000116031446640754400207600ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2008 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ck-log-event.h" #define DEFAULT_LOG_FILENAME LOCALSTATEDIR "/log/ConsoleKit/history" /* Adapted from auditd auditd-event.c */ static gboolean open_log_file (const char *filename, int *fdp, FILE **filep) { int flags; int fd; FILE *file; gboolean ret; ret = FALSE; /* * Likely errors on rotate: ENFILE, ENOMEM, ENOSPC */ flags = O_WRONLY | O_APPEND; #ifdef O_NOFOLLOW flags |= O_NOFOLLOW; #endif retry: fd = g_open (filename, flags, 0600); if (fd < 0) { if (errno == ENOENT) { /* FIXME: should we just skip if file doesn't exist? */ fd = g_open (filename, O_CREAT | O_EXCL | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { g_warning ("Couldn't create log file %s (%s)", filename, g_strerror (errno)); goto out; } close (fd); fd = g_open (filename, flags, 0600); } else if (errno == ENFILE) { /* All system descriptors used, try again... */ goto retry; } if (fd < 0) { g_warning ("Couldn't open log file %s (%s)", filename, g_strerror (errno)); goto out; } } if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) { close (fd); g_warning ("Error setting log file CLOEXEC flag (%s)", g_strerror (errno)); goto out; } if (fchown (fd, 0, 0) == -1) { g_warning ("Error changing owner of log file (%s)", g_strerror (errno)); } file = fdopen (fd, "a"); if (file == NULL) { g_warning ("Error setting up log descriptor (%s)", g_strerror (errno)); close (fd); goto out; } /* Set it to line buffering */ setlinebuf (file); ret = TRUE; if (fdp != NULL) { *fdp = fd; } if (filep != NULL) { *filep = file; } out: return ret; } static gboolean write_log_for_event (CkLogEvent *event) { GString *str; FILE *file; int fd; str = g_string_new (NULL); ck_log_event_to_string (event, str); if (! open_log_file (DEFAULT_LOG_FILENAME, &fd, &file)) { exit (1); } if (file != NULL) { int rc; rc = fprintf (file, "%s\n", str->str); if (rc <= 0) { g_warning ("Record was not written to disk (%s)", g_strerror (errno)); } } else { g_warning ("Log file not open for writing"); } g_string_free (str, TRUE); return TRUE; } int main (int argc, char **argv) { CkLogEvent event; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif memset (&event, 0, sizeof (CkLogEvent)); event.type = CK_LOG_EVENT_SYSTEM_STOP; g_get_current_time (&event.timestamp); write_log_for_event (&event); return 0; } consolekit2-1.2.6/tools/ck-remove-directory.c000066400000000000000000000117061446640754400211750ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (c) 2015, Eric Koegel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "ck-sysdeps.h" static void become_user (uid_t uid) { int res; struct passwd *pwent; errno = 0; pwent = getpwuid (uid); if (pwent == NULL) { g_warning ("Unable to lookup UID: %s", g_strerror (errno)); exit (1); } /* set the group */ errno = 0; res = setegid (pwent->pw_gid); if (res == -1) { g_warning ("Error performing setegid: %s", g_strerror (errno)); exit (1); } /* become the user */ errno = 0; res = seteuid (uid); if (res == -1) { g_warning ("Error performing seteuid: %s", g_strerror (errno)); exit (1); } } static int unlink_cb (const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { int ret = ftwbuf->level > 0 ? remove (fpath) : 0; if (ret) { g_error ("Failed to remove %s, reason was: %s", fpath, strerror(errno)); errno = 0; } return ret; } static int remove_dest_dir (const gchar *dest) { int ret; if ((ret = nftw(dest, unlink_cb, 64, FTW_DEPTH | FTW_PHYS))) { return ret; } errno = 0; ret = seteuid (getuid ()); if (ret == -1) { g_warning ("Error performing seteuid: %s", g_strerror (errno)); exit (1); } ret = remove (dest); if (ret) { g_error ("Failed to remove %s, reason was: %s", dest, strerror (errno)); errno = 0; } return ret; } int main (int argc, char **argv) { GOptionContext *context; gboolean ret; GError *error; static int user_id = -1; static gchar *dest = NULL; static GOptionEntry entries [] = { { "uid", 0, 0, G_OPTION_ARG_INT, &user_id, N_("User ID"), NULL }, { "dest", 0, 0, G_OPTION_ARG_STRING, &dest, N_("Destination to remove"), NULL }, { NULL } }; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif /* For now at least restrict this to root */ if (getuid () != 0) { g_warning (_("You must be root to run this program")); exit (1); } context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); error = NULL; ret = g_option_context_parse (context, &argc, &argv, &error); g_option_context_free (context); if (! ret) { g_warning ("%s", error->message); g_error_free (error); exit (1); } /* Ensure we have a dest and that it starts with the correct prefix * so we don't remove something important. */ if (dest == NULL || !g_str_has_prefix (dest, RUNDIR "/user/")) { g_warning ("Invalid Dest"); exit (1); } become_user (user_id); return remove_dest_dir (dest) == 0 ? 0 : 1; } consolekit2-1.2.6/tools/freebsd/000077500000000000000000000000001446640754400165445ustar00rootroot00000000000000consolekit2-1.2.6/tools/freebsd/Makefile.am000066400000000000000000000015351446640754400206040ustar00rootroot00000000000000## We require new-style dependency handling. AUTOMAKE_OPTIONS = 1.7 NULL = SUBDIRS = \ $(NULL) scriptdir = $(libdir)/ConsoleKit/scripts script_SCRIPTS = \ ck-system-stop \ ck-system-restart \ ck-system-suspend \ ck-system-hibernate \ ck-system-hybridsleep \ ck-get-x11-display-device \ ck-get-x11-server-pid \ $(NULL) EXTRA_DIST = \ $(script_SCRIPTS) \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in check: for f in $(script_SCRIPTS); do \ echo -n "Validate shell syntax in $$f : "; \ sh -n $(srcdir)/$$f 2> sh.error;\ if test -s sh.error; then \ echo failed; \ cat sh.error; \ rm -f sh.error; \ exit 1; \ else \ echo ok; \ rm -f sh.error; \ fi; \ done; consolekit2-1.2.6/tools/freebsd/ck-get-x11-display-device000077500000000000000000000014621446640754400231560ustar00rootroot00000000000000#!/bin/sh FSTAT="/usr/bin/fstat" GREP="/usr/bin/grep" AWK="/usr/bin/awk" SED="/usr/bin/sed" CAT="/bin/cat" dispnum=0 if [ x"$1" = x"--display" ]; then if [ $# != 2 ]; then echo "usage: $0 [--display DISPLAY]" exit 1 fi DISPLAY=$2 fi if [ ! -z "${DISPLAY}" ]; then dispnum=$(echo ${DISPLAY} | ${SED} -E -e 's|:([0-9]+).*|\1|') fi if [ ! -f "/tmp/.X${dispnum}-lock" ]; then echo "ERROR: Failed to find X lock file for display ${dispnum}" exit 1 fi pid=$(${CAT} "/tmp/.X${dispnum}-lock") device=$(${FSTAT} -p ${pid} | ${GREP} ttyv | ${AWK} '{print $8}') if [ -z "${device}" ]; then echo "ERROR: Failed to find TTY device for X server on display ${dispnum}" exit 1 fi ret="" for dev in ${device}; do if [ "${dev}" \> "${ret}" ]; then ret=${dev} fi done echo "/dev/${dev}" consolekit2-1.2.6/tools/freebsd/ck-get-x11-server-pid000077500000000000000000000005161446640754400223330ustar00rootroot00000000000000#!/bin/sh SED="/usr/bin/sed" CAT="/bin/cat" dispnum=0 if [ ! -z "${DISPLAY}" ]; then dispnum=$(echo ${DISPLAY} | ${SED} -E -e 's|:([0-9]+).*|\1|') fi if [ ! -f "/tmp/.X${dispnum}-lock" ]; then echo "ERROR: Failed to find X lock file for display ${dispnum}" exit 1 fi pid=$(${CAT} "/tmp/.X${dispnum}-lock") echo ${pid} consolekit2-1.2.6/tools/freebsd/ck-system-hibernate000066400000000000000000000002731446640754400223470ustar00rootroot00000000000000#!/bin/sh #Try for common tools if [ -x "/sbin/acpiconf" ] ; then /sbin/acpiconf -s 4 exit $? elif [ -x "/usr/sbin/acpiconf" ] ; then /usr/sbin/acpiconf -s 4 exit $? else exit 1 fi consolekit2-1.2.6/tools/freebsd/ck-system-hybridsleep000066400000000000000000000000441446640754400227140ustar00rootroot00000000000000#!/bin/sh # Not implemented exit 1 consolekit2-1.2.6/tools/freebsd/ck-system-restart000077500000000000000000000002771446640754400221010ustar00rootroot00000000000000#!/bin/sh #Try for common tools if [ -x "/sbin/shutdown" ] ; then /sbin/shutdown -r now exit $? elif [ -x "/usr/sbin/shutdown" ] ; then /usr/sbin/shutdown -r now exit $? else exit 1 fi consolekit2-1.2.6/tools/freebsd/ck-system-stop000077500000000000000000000005171446640754400213770ustar00rootroot00000000000000#!/bin/sh unsupported() { echo "org.freedesktop.Hal.Device.SystemPowerManagement.NotSupported" >&2 echo "No shutdown command found" >&2 exit 1 } #Try for common tools if [ -x "/sbin/shutdown" ] ; then /sbin/shutdown -p now exit $? elif [ -x "/usr/sbin/shutdown" ] ; then /usr/sbin/shutdown -p now exit $? else unsupported fi consolekit2-1.2.6/tools/freebsd/ck-system-suspend000066400000000000000000000002731446640754400220670ustar00rootroot00000000000000#!/bin/sh #Try for common tools if [ -x "/sbin/acpiconf" ] ; then /sbin/acpiconf -s 3 exit $? elif [ -x "/usr/sbin/acpiconf" ] ; then /usr/sbin/acpiconf -s 3 exit $? else exit 1 fi consolekit2-1.2.6/tools/linux/000077500000000000000000000000001446640754400162715ustar00rootroot00000000000000consolekit2-1.2.6/tools/linux/.gitignore000066400000000000000000000001351446640754400202600ustar00rootroot00000000000000*.la *.lo *.o .deps .libs Makefile Makefile.in ck-collect-session-info ck-get-x11-server-pid consolekit2-1.2.6/tools/linux/Makefile.am000066400000000000000000000014571446640754400203340ustar00rootroot00000000000000## We require new-style dependency handling. AUTOMAKE_OPTIONS = 1.7 NULL = SUBDIRS = \ $(NULL) scriptdir = $(libdir)/ConsoleKit/scripts script_SCRIPTS = \ ck-system-stop \ ck-system-restart \ ck-system-suspend \ ck-system-hibernate \ ck-system-hybridsleep \ $(NULL) EXTRA_DIST = \ $(script_SCRIPTS) \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in check: for f in $(script_SCRIPTS); do \ echo -n "Validate bash syntax in $$f : "; \ bash -n $(srcdir)/$$f 2> bash.error;\ if test -s bash.error; then \ echo failed; \ cat bash.error; \ rm -f bash.error; \ exit 1; \ else \ echo ok; \ rm -f bash.error; \ fi; \ done; consolekit2-1.2.6/tools/linux/ck-system-hibernate000066400000000000000000000000501446640754400220650ustar00rootroot00000000000000#!/bin/sh echo disk > /sys/power/state consolekit2-1.2.6/tools/linux/ck-system-hybridsleep000066400000000000000000000001071446640754400224410ustar00rootroot00000000000000#!/bin/sh echo suspend > /sys/power/disk echo disk > /sys/power/state consolekit2-1.2.6/tools/linux/ck-system-restart000077500000000000000000000000331446640754400216140ustar00rootroot00000000000000#!/bin/sh shutdown -r now consolekit2-1.2.6/tools/linux/ck-system-stop000077500000000000000000000000331446640754400211150ustar00rootroot00000000000000#!/bin/sh shutdown -h now consolekit2-1.2.6/tools/linux/ck-system-suspend000066400000000000000000000000471446640754400216130ustar00rootroot00000000000000#!/bin/sh echo mem > /sys/power/state consolekit2-1.2.6/tools/list-sessions.c000066400000000000000000000334071446640754400201240ustar00rootroot00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2006 William Jon McCann * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #define CK_NAME "org.freedesktop.ConsoleKit" #define CK_INTERFACE "org.freedesktop.ConsoleKit" #define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" #define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" static gboolean get_value (GDBusProxy *proxy, const char *method, const char *variant_type, gpointer val) { GError *error; GVariant *res; error = NULL; res = g_dbus_proxy_call_sync (proxy, method, g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 6000, NULL, &error); if (res == NULL) { g_debug ("%s failed: %s", method, error->message); g_clear_error (&error); return FALSE; } else { g_variant_get (res, variant_type, val, NULL); g_variant_unref (res); } return TRUE; } static gboolean get_property (GDBusProxy *proxy, const char *property, const char *variant_type, gpointer val) { GVariant *res; res = g_dbus_proxy_get_cached_property (proxy, property); if (res == NULL) { g_debug ("failed accessing %s", property); return FALSE; } else { g_variant_get (res, variant_type, val, NULL); g_variant_unref (res); } return TRUE; } static gboolean get_uint (GDBusProxy *proxy, const char *method, guint *val) { return get_value (proxy, method, "(u)", val); } static gboolean get_uint_property (GDBusProxy *proxy, const char *property, guint *val) { return get_property (proxy, property, "u", val); } static gboolean get_path (GDBusProxy *proxy, const char *method, char **str) { return get_value (proxy, method, "(o)", str); } static gboolean get_string (GDBusProxy *proxy, const char *method, char **str) { return get_value (proxy, method, "(s)", str); } static gboolean get_boolean (GDBusProxy *proxy, const char *method, gboolean *value) { return get_value (proxy, method, "(b)", value); } static char * get_real_name (uid_t uid) { struct passwd *pwent; char *realname; realname = NULL; pwent = getpwuid (uid); if (pwent != NULL && pwent->pw_gecos && *pwent->pw_gecos != '\0') { char **gecos_fields; char **name_parts; /* split the gecos field and substitute '&' */ gecos_fields = g_strsplit (pwent->pw_gecos, ",", 0); name_parts = g_strsplit (gecos_fields[0], "&", 0); pwent->pw_name[0] = g_ascii_toupper (pwent->pw_name[0]); realname = g_strjoinv (pwent->pw_name, name_parts); g_strfreev (gecos_fields); g_strfreev (name_parts); } return realname; } static void list_session (GDBusConnection *connection, const char *ssid) { GDBusProxy *proxy; guint uid = 0; char *realname; char *sid; char *lsid; char *session_type; char *session_class; char *session_state; char *session_service; char *x11_display; char *x11_display_device; char *display_device; char *remote_host_name; char *creation_time; char *idle_since_hint; char *runtime_dir; gboolean is_active; gboolean is_local; char *short_sid; char *short_ssid; guint vtnum; GError *error = NULL; proxy = g_dbus_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_NONE, NULL, CK_NAME, ssid, CK_SESSION_INTERFACE, NULL, &error); if (proxy == NULL) { g_print ("error creating proxy, %s", error->message); g_clear_error (&error); return; } sid = NULL; lsid = NULL; session_type = NULL; session_class = NULL; session_state = NULL; session_service = NULL; x11_display = NULL; x11_display_device = NULL; display_device = NULL; remote_host_name = NULL; creation_time = NULL; idle_since_hint = NULL; vtnum = -1; get_uint (proxy, "GetUnixUser", &uid); get_path (proxy, "GetSeatId", &sid); get_string (proxy, "GetLoginSessionId", &lsid); get_string (proxy, "GetSessionType", &session_type); get_string (proxy, "GetSessionClass", &session_class); get_string (proxy, "GetSessionState", &session_state); get_string (proxy, "GetSessionService", &session_service); get_string (proxy, "GetX11Display", &x11_display); get_string (proxy, "GetX11DisplayDevice", &x11_display_device); get_string (proxy, "GetDisplayDevice", &display_device); get_string (proxy, "GetRemoteHostName", &remote_host_name); get_boolean (proxy, "IsActive", &is_active); get_boolean (proxy, "IsLocal", &is_local); get_string (proxy, "GetCreationTime", &creation_time); get_string (proxy, "GetIdleSinceHint", &idle_since_hint); get_string (proxy, "GetXDGRuntimeDir", &runtime_dir); get_uint_property (proxy, "VTNr", &vtnum); realname = get_real_name (uid); short_sid = g_path_get_basename(sid); short_ssid = g_path_get_basename(ssid); printf ("%s:\n" "\tunix-user = '%d'\n" "\trealname = '%s'\n" "\tseat = '%s'\n" "\tsession-type = '%s'\n" "\tsession-class = '%s'\n" "\tsession-state = '%s'\n" "\tsession-service = '%s'\n" "\tactive = %s\n" "\tx11-display = '%s'\n" "\tx11-display-device = '%s'\n" "\tdisplay-device = '%s'\n" "\tremote-host-name = '%s'\n" "\tis-local = %s\n" "\ton-since = '%s'\n" "\tlogin-session-id = '%s'\n" "\tXDG_RUNTIME_DIR = '%s'", short_ssid, uid, realname, short_sid, session_type, session_class, session_state, session_service, is_active ? "TRUE" : "FALSE", x11_display, x11_display_device, display_device, remote_host_name, is_local ? "TRUE" : "FALSE", creation_time, lsid, runtime_dir); if (vtnum != 0) { printf ("\n\tVTNr = '%u'", vtnum); } if (idle_since_hint != NULL && idle_since_hint[0] != '\0') { printf ("\n\tidle-since-hint = '%s'", idle_since_hint); } printf ("\n"); g_free (idle_since_hint); g_free (creation_time); g_free (remote_host_name); g_free (realname); g_free (sid); g_free (short_sid); g_free (short_ssid); g_free (lsid); g_free (session_type); g_free (session_class); g_free (session_state); g_free (x11_display); g_free (x11_display_device); g_free (display_device); g_free (runtime_dir); g_object_unref (proxy); } static void list_sessions (GDBusConnection *connection, const char *sid) { GDBusProxy *proxy; GError *error; GVariant *res; GVariantIter *iter; proxy = g_dbus_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_NONE, NULL, CK_NAME, sid, CK_SEAT_INTERFACE, NULL, &error); if (proxy == NULL) { g_print ("error creating proxy, %s", error->message); g_clear_error (&error); return; } error = NULL; res = g_dbus_proxy_call_sync (proxy, "GetSessions", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 6000, NULL, &error); if (res == NULL) { g_warning ("Failed to get list of sessions for %s: %s", sid, error->message); g_clear_error (&error); goto out; } g_variant_get (res, "(ao)", &iter); while (g_variant_iter_next (iter, "o", &sid)) { list_session (connection, sid); } g_variant_iter_free (iter); g_variant_unref (res); out: g_object_unref (proxy); } static void list_seats (GDBusConnection *connection) { GDBusProxy *proxy; GError *error; GVariant *res; GVariantIter *iter; gchar *path = NULL; proxy = g_dbus_proxy_new_sync (connection, G_DBUS_PROXY_FLAGS_NONE, NULL, CK_NAME, CK_MANAGER_PATH, CK_MANAGER_INTERFACE, NULL, &error); if (proxy == NULL) { g_print ("error creating proxy, %s", error->message); g_clear_error (&error); return; } error = NULL; res = g_dbus_proxy_call_sync (proxy, "GetSeats", g_variant_new ("()"), G_DBUS_CALL_FLAGS_NONE, 6000, NULL, &error); if (res == NULL) { g_warning ("Failed to get list of seats: %s", error->message); g_clear_error (&error); goto out; } g_variant_get (res, "(ao)", &iter); while (g_variant_iter_next (iter, "o", &path)) { list_sessions (connection, path); } g_variant_iter_free (iter); g_variant_unref (res); out: g_object_unref (proxy); } int main (int argc, char **argv) { GDBusConnection *connection; GOptionContext *context; gboolean retval; GError *error = NULL; static gboolean do_version = FALSE; static GOptionEntry entries [] = { { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL }, { NULL } }; /* Setup for i18n */ setlocale(LC_ALL, ""); #ifdef ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); retval = g_option_context_parse (context, &argc, &argv, &error); g_option_context_free (context); if (! retval) { g_warning ("%s", error->message); g_error_free (error); exit (1); } if (do_version) { g_print ("%s %s\n", argv [0], VERSION); exit (1); } error = NULL; connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (connection == NULL) { g_message ("Failed to connect to the D-Bus daemon: %s", error->message); g_error_free (error); exit (1); } list_seats (connection); return 0; } consolekit2-1.2.6/tools/netbsd/000077500000000000000000000000001446640754400164115ustar00rootroot00000000000000consolekit2-1.2.6/tools/netbsd/Makefile.am000066400000000000000000000014521446640754400204470ustar00rootroot00000000000000## We require new-style dependency handling. AUTOMAKE_OPTIONS = 1.7 NULL = SUBDIRS = \ $(NULL) scriptdir = $(prefix)/lib/ConsoleKit/scripts script_SCRIPTS = \ ck-system-stop \ ck-system-restart \ ck-system-suspend \ ck-system-hibernate \ ck-system-hybridsleep \ $(NULL) EXTRA_DIST = \ $(script_SCRIPTS) \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in check: for f in $(script_SCRIPTS); do \ echo -n "Validate shell syntax in $$f : "; \ sh -n $(srcdir)/$$f 2> sh.error;\ if test -s sh.error; then \ echo failed; \ cat sh.error; \ rm -f sh.error; \ exit 1; \ else \ echo ok; \ rm -f sh.error; \ fi; \ done; consolekit2-1.2.6/tools/netbsd/ck-system-hibernate000066400000000000000000000000441446640754400222100ustar00rootroot00000000000000#!/bin/sh # Not implemented exit 1 consolekit2-1.2.6/tools/netbsd/ck-system-hybridsleep000066400000000000000000000000441446640754400225610ustar00rootroot00000000000000#!/bin/sh # Not implemented exit 1 consolekit2-1.2.6/tools/netbsd/ck-system-restart000077500000000000000000000000411446640754400217330ustar00rootroot00000000000000#!/bin/sh /sbin/shutdown -r now consolekit2-1.2.6/tools/netbsd/ck-system-stop000077500000000000000000000000411446640754400212340ustar00rootroot00000000000000#!/bin/sh /sbin/shutdown -p now consolekit2-1.2.6/tools/netbsd/ck-system-suspend000066400000000000000000000005421446640754400217330ustar00rootroot00000000000000#!/bin/sh if /sbin/sysctl -q hw.acpi.sleep.state; then /sbin/sysctl -w hw.acpi.sleep.state=3 elif /sbin/sysctl -q machdep.xen.suspend; then /sbin/sysctl -w machdep.xen.suspend=1 elif test -x /usr/sbin/apm; then if test -f /etc/rc.d/apmd && /etc/rc.d/apmd onestatus > /dev/null; then /usr/sbin/apm -z else /usr/sbin/apm -d -z fi else exit 1 fi consolekit2-1.2.6/tools/openbsd/000077500000000000000000000000001446640754400165645ustar00rootroot00000000000000consolekit2-1.2.6/tools/openbsd/Makefile.am000066400000000000000000000014521446640754400206220ustar00rootroot00000000000000## We require new-style dependency handling. AUTOMAKE_OPTIONS = 1.7 NULL = SUBDIRS = \ $(NULL) scriptdir = $(prefix)/lib/ConsoleKit/scripts script_SCRIPTS = \ ck-system-stop \ ck-system-restart \ ck-system-suspend \ ck-system-hibernate \ ck-system-hybridsleep \ $(NULL) EXTRA_DIST = \ $(script_SCRIPTS) \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in check: for f in $(script_SCRIPTS); do \ echo -n "Validate shell syntax in $$f : "; \ sh -n $(srcdir)/$$f 2> sh.error;\ if test -s sh.error; then \ echo failed; \ cat sh.error; \ rm -f sh.error; \ exit 1; \ else \ echo ok; \ rm -f sh.error; \ fi; \ done; consolekit2-1.2.6/tools/openbsd/ck-system-hibernate000066400000000000000000000001661446640754400223700ustar00rootroot00000000000000#!/bin/sh # add small time buffer for a screen lock to settle first (when called by a DE) (sleep 2; /usr/sbin/ZZZ) & consolekit2-1.2.6/tools/openbsd/ck-system-hybridsleep000066400000000000000000000000441446640754400227340ustar00rootroot00000000000000#!/bin/sh # Not implemented exit 1 consolekit2-1.2.6/tools/openbsd/ck-system-restart000077500000000000000000000000411446640754400221060ustar00rootroot00000000000000#!/bin/sh /sbin/shutdown -r now consolekit2-1.2.6/tools/openbsd/ck-system-stop000077500000000000000000000000421446640754400214100ustar00rootroot00000000000000#!/bin/sh /sbin/shutdown -hp now consolekit2-1.2.6/tools/openbsd/ck-system-suspend000066400000000000000000000001661446640754400221100ustar00rootroot00000000000000#!/bin/sh # add small time buffer for a screen lock to settle first (when called by a DE) (sleep 2; /usr/sbin/zzz) & consolekit2-1.2.6/tools/solaris/000077500000000000000000000000001446640754400166065ustar00rootroot00000000000000consolekit2-1.2.6/tools/solaris/Makefile.am000066400000000000000000000014611446640754400206440ustar00rootroot00000000000000## We require new-style dependency handling. AUTOMAKE_OPTIONS = 1.7 NULL = SUBDIRS = \ $(NULL) scriptdir = $(libdir)/ConsoleKit/scripts script_SCRIPTS = \ ck-system-stop \ ck-system-restart \ ck-system-suspend \ ck-system-hibernate \ ck-system-hybridsleep \ $(NULL) EXTRA_DIST = \ $(script_SCRIPTS) \ $(NULL) MAINTAINERCLEANFILES = \ *~ \ Makefile.in check: for f in $(script_SCRIPTS); do \ echo -n "Validate bash syntax in $$f : "; \ bash -n $(srcdir)/$$f 2> bash.error;\ if test -s bash.error; then \ echo failed; \ cat bash.error; \ rm -f bash.error; \ exit 1; \ else \ echo ok; \ rm -f bash.error; \ fi; \ done; consolekit2-1.2.6/tools/solaris/ck-system-hibernate000066400000000000000000000000521446640754400224040ustar00rootroot00000000000000#!/bin/sh # FIXME: Implement this exit 1 consolekit2-1.2.6/tools/solaris/ck-system-hybridsleep000066400000000000000000000000521446640754400227550ustar00rootroot00000000000000#!/bin/sh # FIXME: Implement this exit 1 consolekit2-1.2.6/tools/solaris/ck-system-restart000077500000000000000000000000301446640754400221260ustar00rootroot00000000000000#!/bin/sh /sbin/init 6 consolekit2-1.2.6/tools/solaris/ck-system-stop000077500000000000000000000000301446640754400214270ustar00rootroot00000000000000#!/bin/sh /sbin/init 5 consolekit2-1.2.6/tools/solaris/ck-system-suspend000066400000000000000000000000521446640754400221240ustar00rootroot00000000000000#!/bin/sh # FIXME: Implement this exit 1 consolekit2-1.2.6/tools/udev-acl.c000066400000000000000000000342601446640754400170030ustar00rootroot00000000000000/* * Copyright (C) 2009 Kay Sievers * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details: */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int debug; enum{ ACTION_NONE = 0, ACTION_REMOVE, ACTION_ADD, ACTION_CHANGE }; static int set_facl(const char* filename, uid_t uid, int add) { int get; acl_t acl; acl_entry_t entry = NULL; acl_entry_t e; acl_permset_t permset; int ret; /* don't touch ACLs for root */ if (uid == 0) return 0; /* read current record */ acl = acl_get_file(filename, ACL_TYPE_ACCESS); if (!acl) return -1; /* locate ACL_USER entry for uid */ get = acl_get_entry(acl, ACL_FIRST_ENTRY, &e); while (get == 1) { acl_tag_t t; acl_get_tag_type(e, &t); if (t == ACL_USER) { uid_t *u; u = (uid_t*)acl_get_qualifier(e); if (u == NULL) { ret = -1; goto out; } if (*u == uid) { entry = e; acl_free(u); break; } acl_free(u); } get = acl_get_entry(acl, ACL_NEXT_ENTRY, &e); } /* remove ACL_USER entry for uid */ if (!add) { if (entry == NULL) { ret = 0; goto out; } acl_delete_entry(acl, entry); goto update; } /* create ACL_USER entry for uid */ if (entry == NULL) { ret = acl_create_entry(&acl, &entry); if (ret != 0) goto out; acl_set_tag_type(entry, ACL_USER); acl_set_qualifier(entry, &uid); } /* add permissions for uid */ acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ|ACL_WRITE); update: /* update record */ if (debug) printf("%c%u %s\n", add ? '+' : '-', uid, filename); acl_calc_mask(&acl); ret = acl_set_file(filename, ACL_TYPE_ACCESS, acl); out: acl_free(acl); return ret; } /* check if a given uid is listed */ static int uid_in_list(GSList *list, uid_t uid) { GSList *l; for (l = list; l != NULL; l = g_slist_next(l)) if (uid == GPOINTER_TO_UINT(l->data)) return 1; return 0; } /* return list of current uids of local active sessions */ static GSList *uids_with_local_active_session(const char *own_id) { GSList *list = NULL; GKeyFile *keyfile; keyfile = g_key_file_new(); if (g_key_file_load_from_file(keyfile, RUNDIR "/ConsoleKit/database", 0, NULL)) { gchar **groups; groups = g_key_file_get_groups(keyfile, NULL); if (groups != NULL) { int i; for (i = 0; groups[i] != NULL; i++) { uid_t u; if (!g_str_has_prefix(groups[i], "Session ")) continue; if (own_id != NULL &&g_str_has_suffix(groups[i], own_id)) continue; if (!g_key_file_get_boolean(keyfile, groups[i], "is_local", NULL)) continue; if (!g_key_file_get_boolean(keyfile, groups[i], "is_active", NULL)) continue; u = g_key_file_get_integer(keyfile, groups[i], "uid", NULL); if (u > 0 && !uid_in_list(list, u)) list = g_slist_prepend(list, GUINT_TO_POINTER(u)); } g_strfreev(groups); } } g_key_file_free(keyfile); return list; } /* ConsoleKit calls us with special variables */ static int consolekit_called(const char *ck_action, uid_t *uid, uid_t *uid2, const char **remove_session_id, int *action) { int a = ACTION_NONE; uid_t u = 0; uid_t u2 = 0; const char *s; const char *s2; const char *old_session = NULL; if (ck_action == NULL || strcmp(ck_action, "seat_active_session_changed") != 0) return -1; /* We can have one of: remove, add, change, no-change */ s = getenv("CK_SEAT_OLD_SESSION_ID"); s2 = getenv("CK_SEAT_SESSION_ID"); if (s == NULL && s2 == NULL) { return -1; } else if (s2 == NULL) { a = ACTION_REMOVE; } else if (s == NULL) { a = ACTION_ADD; } else { a = ACTION_CHANGE; } switch (a) { case ACTION_ADD: s = getenv("CK_SEAT_SESSION_USER_UID"); if (s == NULL) return -1; u = strtoul(s, NULL, 10); s = getenv("CK_SEAT_SESSION_IS_LOCAL"); if (s == NULL) return -1; if (strcmp(s, "true") != 0) return 0; break; case ACTION_REMOVE: s = getenv("CK_SEAT_OLD_SESSION_USER_UID"); if (s == NULL) return -1; u = strtoul(s, NULL, 10); s = getenv("CK_SEAT_OLD_SESSION_IS_LOCAL"); if (s == NULL) return -1; if (strcmp(s, "true") != 0) return 0; old_session = getenv("CK_SEAT_OLD_SESSION_ID"); if (old_session == NULL) return -1; break; case ACTION_CHANGE: s = getenv("CK_SEAT_OLD_SESSION_USER_UID"); if (s == NULL) return -1; u = strtoul(s, NULL, 10); s = getenv("CK_SEAT_SESSION_USER_UID"); if (s == NULL) return -1; u2 = strtoul(s, NULL, 10); s = getenv("CK_SEAT_OLD_SESSION_IS_LOCAL"); s2 = getenv("CK_SEAT_SESSION_IS_LOCAL"); if (s == NULL || s2 == NULL) return -1; /* don't process non-local session changes */ if (strcmp(s, "true") != 0 && strcmp(s2, "true") != 0) return 0; if (strcmp(s, "true") == 0 && strcmp(s2, "true") == 0) { /* process the change */ if (u == u2) { /* special case: we noop if we are * changing between local sessions for * the same uid */ a = ACTION_NONE; } old_session = getenv("CK_SEAT_OLD_SESSION_ID"); if (old_session == NULL) return -1; } else if (strcmp(s, "true") == 0) { /* only process the removal */ a = ACTION_REMOVE; old_session = getenv("CK_SEAT_OLD_SESSION_ID"); if (old_session == NULL) return -1; } else if (strcmp(s2, "true") == 0) { /* only process the addition */ a = ACTION_ADD; u = u2; } break; } *remove_session_id = old_session; *uid = u; *uid2 = u2; *action = a; return 0; } /* add or remove a ACL for a given uid from all matching devices */ static void apply_acl_to_devices(uid_t uid, int add) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *list_entry; /* iterate over all devices tagged with ACL_SET */ udev = udev_new(); enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_tag(enumerate, "udev-acl"); udev_enumerate_scan_devices(enumerate); udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { struct udev_device *device; const char *node; device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), udev_list_entry_get_name(list_entry)); if (device == NULL) continue; node = udev_device_get_devnode(device); if (node == NULL) { udev_device_unref(device); continue; } set_facl(node, uid, add); udev_device_unref(device); } udev_enumerate_unref(enumerate); udev_unref(udev); } static void remove_uid (uid_t uid, const char *remove_session_id) { /* * Remove ACL for given uid from all matching devices * when there is currently no local active session. */ GSList *list; list = uids_with_local_active_session(remove_session_id); if (!uid_in_list(list, uid)) apply_acl_to_devices(uid, 0); g_slist_free(list); } int main (int argc, char* argv[]) { static const struct option options[] = { { "action", required_argument, NULL, 'a' }, { "device", required_argument, NULL, 'D' }, { "user", required_argument, NULL, 'u' }, { "debug", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, {} }; int action = -1; const char *device = NULL; bool uid_given = false; uid_t uid = 0; uid_t uid2 = 0; const char* remove_session_id = NULL; int rc = 0; while (1) { int option; option = getopt_long(argc, argv, "+a:D:u:dh", options, NULL); if (option == -1) break; switch (option) { case 'a': if (strcmp(optarg, "remove") == 0) action = ACTION_REMOVE; else action = ACTION_ADD; break; case 'D': device = optarg; break; case 'u': uid_given = true; uid = strtoul(optarg, NULL, 10); break; case 'd': debug = 1; break; case 'h': printf("Usage: udev-acl --action=ACTION [--device=DEVICEFILE] [--user=UID]\n\n"); goto out; } } if (action < 0 && device == NULL && !uid_given) if (!consolekit_called(argv[optind], &uid, &uid2, &remove_session_id, &action)) uid_given = true; if (action < 0) { fprintf(stderr, "missing action\n\n"); rc = 2; goto out; } if (device != NULL && uid_given) { fprintf(stderr, "only one option, --device=DEVICEFILE or --user=UID expected\n\n"); rc = 3; goto out; } if (uid_given) { switch (action) { case ACTION_ADD: /* Add ACL for given uid to all matching devices. */ apply_acl_to_devices(uid, 1); break; case ACTION_REMOVE: remove_uid(uid, remove_session_id); break; case ACTION_CHANGE: remove_uid(uid, remove_session_id); apply_acl_to_devices(uid2, 1); break; case ACTION_NONE: goto out; break; default: g_assert_not_reached(); break; } } else if (device != NULL) { /* * Add ACLs for all current session uids to a given device. * * Or remove ACLs for uids which do not have any current local * active session. Remove is not really interesting, because in * most cases the device node is removed anyway. */ GSList *list; GSList *l; list = uids_with_local_active_session(NULL); for (l = list; l != NULL; l = g_slist_next(l)) { uid_t u; u = GPOINTER_TO_UINT(l->data); if (action == ACTION_ADD || !uid_in_list(list, u)) set_facl(device, u, action == ACTION_ADD); } g_slist_free(list); } else { fprintf(stderr, "--device=DEVICEFILE or --user=UID expected\n\n"); rc = 3; } out: return rc; }