Adding upstream version 48.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
ee81d57d08
commit
83b37a3d94
341 changed files with 229581 additions and 0 deletions
153
.gitignore
vendored
Normal file
153
.gitignore
vendored
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
*~
|
||||||
|
*.cat
|
||||||
|
*.cat.m
|
||||||
|
*.gmo
|
||||||
|
*.lo
|
||||||
|
*.mo
|
||||||
|
.*.*.mo
|
||||||
|
*.msg
|
||||||
|
*.o
|
||||||
|
*.old.po
|
||||||
|
*.pox
|
||||||
|
*.tab.c
|
||||||
|
.*.swp
|
||||||
|
ABOUT-NLS
|
||||||
|
at-spi-registryd-wrapper.desktop.in
|
||||||
|
./autom4te.cache
|
||||||
|
.deps
|
||||||
|
_libs
|
||||||
|
.libs
|
||||||
|
cat-id-tbl.tmp
|
||||||
|
config.cache
|
||||||
|
config.h
|
||||||
|
config.log
|
||||||
|
config.lt
|
||||||
|
config.rpath
|
||||||
|
config.status
|
||||||
|
config.status.lineno
|
||||||
|
configure.lineno
|
||||||
|
gdm.conf
|
||||||
|
gdm.conf-custom
|
||||||
|
gdm-display-glue.h
|
||||||
|
gdm-display-glue.c
|
||||||
|
gdm-local-display-glue.h
|
||||||
|
gdm-local-display-glue.c
|
||||||
|
gdm-local-display-factory-glue.h
|
||||||
|
gdm-local-display-factory-glue.c
|
||||||
|
gdm-manager-glue.c
|
||||||
|
gdm-manager-glue.h
|
||||||
|
gdm.pot
|
||||||
|
gdm-restart
|
||||||
|
gdm-safe-restart
|
||||||
|
gdm.schemas
|
||||||
|
gdm-session-glue.h
|
||||||
|
gdm-session-glue.c
|
||||||
|
gdm-session-worker-glue.h
|
||||||
|
gdm-session-worker-glue.c
|
||||||
|
gdm-static-display-glue.h
|
||||||
|
gdm-static-display-glue.c
|
||||||
|
gdm-static-factory-display-glue.h
|
||||||
|
gdm-stop
|
||||||
|
gdm-transient-display-glue.h
|
||||||
|
gdm-transient-display-glue.c
|
||||||
|
gdm-xdmcp-display-glue.h
|
||||||
|
gdm-xdmcp-display-glue.c
|
||||||
|
gdm-xdmcp-chooser-display-glue.h
|
||||||
|
gdm-xdmcp-greeter-display-glue.h
|
||||||
|
gdm-greeter-glue.h
|
||||||
|
gdm-greeter-glue.c
|
||||||
|
GNOME_FastUserSwitchApplet.server
|
||||||
|
GNOME_FastUserSwitchApplet.server.in
|
||||||
|
gnome-power-manager.desktop.in
|
||||||
|
gnome-settings-daemon.desktop.in
|
||||||
|
GPATH
|
||||||
|
GRTAGS
|
||||||
|
GSYMS
|
||||||
|
GTAGS
|
||||||
|
in
|
||||||
|
Init
|
||||||
|
.intltool-merge-cache
|
||||||
|
libgdmcommon.la
|
||||||
|
libgdmuser.la
|
||||||
|
libnotificationarea.la
|
||||||
|
libtool
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
Makefile.in.in
|
||||||
|
na-marshal.c
|
||||||
|
na-marshal.h
|
||||||
|
PostSession
|
||||||
|
POTFILES
|
||||||
|
PreSession
|
||||||
|
so_locations
|
||||||
|
stamp-h1
|
||||||
|
stamp-it
|
||||||
|
tags
|
||||||
|
TAGS
|
||||||
|
Xsession
|
||||||
|
INSTALL
|
||||||
|
aclocal.m4
|
||||||
|
autom4te.cache/
|
||||||
|
common/test-log
|
||||||
|
compile
|
||||||
|
config.guess
|
||||||
|
config.h.in
|
||||||
|
config.sub
|
||||||
|
configure
|
||||||
|
daemon/gdm
|
||||||
|
daemon/gdm-session-worker
|
||||||
|
daemon/gdm-wayland-session
|
||||||
|
daemon/gdm-x-session
|
||||||
|
daemon/test-session-client
|
||||||
|
daemon/test-external-greeter
|
||||||
|
daemon/gdm-session-enum-types.c
|
||||||
|
daemon/gdm-session-enum-types.h
|
||||||
|
data/applications/gnome-mag.desktop
|
||||||
|
data/applications/gnome-shell.desktop
|
||||||
|
data/applications/gnome-shell-wayland.desktop
|
||||||
|
data/applications/gok.desktop
|
||||||
|
data/applications/orca-screen-reader.desktop
|
||||||
|
data/autostart/caribou-autostart.desktop
|
||||||
|
depcomp
|
||||||
|
libgdm/gdm-client-glue.h
|
||||||
|
libgdm/gdm-client-glue.c
|
||||||
|
libgdm/gdm-manager-glue.h
|
||||||
|
libgdm/gdm-manager-glue.c
|
||||||
|
gui/simple-chooser/gdm-host-chooser
|
||||||
|
gui/simple-chooser/gdm-simple-chooser
|
||||||
|
install-sh
|
||||||
|
intltool-extract.in
|
||||||
|
intltool-merge.in
|
||||||
|
intltool-update.in
|
||||||
|
ltmain.sh
|
||||||
|
m4/*.m4
|
||||||
|
missing
|
||||||
|
mkinstalldirs
|
||||||
|
tests/m-common
|
||||||
|
utils/gdmflexiserver
|
||||||
|
*.gschema.valid
|
||||||
|
*.gschema.xml
|
||||||
|
*.la
|
||||||
|
*.pc
|
||||||
|
*.gir
|
||||||
|
*.typelib
|
||||||
|
*.tar.*
|
||||||
|
gdm-smartcard-worker
|
||||||
|
dconf-override-db
|
||||||
|
|
||||||
|
docs/*/*.stamp
|
||||||
|
docs/*/legal.xml
|
||||||
|
docs/*/index.docbook
|
||||||
|
|
||||||
|
po/*.gmo
|
||||||
|
po/*.header
|
||||||
|
po/*.sed
|
||||||
|
po/*.sin
|
||||||
|
po/.intltool-merge-cache
|
||||||
|
po/Makefile.in.in
|
||||||
|
po/Makevars.template
|
||||||
|
po/POTFILES
|
||||||
|
po/Rules-quot
|
||||||
|
po/stamp-it
|
||||||
|
|
||||||
|
test-driver
|
113
.gitlab-ci.yml
Normal file
113
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
include:
|
||||||
|
- https://gitlab.gnome.org/Infrastructure/freedesktop-ci-templates/-/raw/master/templates/fedora.yml
|
||||||
|
- component: "gitlab.gnome.org/GNOME/citemplates/release-service@master"
|
||||||
|
inputs:
|
||||||
|
job-stage: "release"
|
||||||
|
dist-job-name: "build-fedora"
|
||||||
|
tarball-artifact-path: "${TARBALL_ARTIFACT_PATH}"
|
||||||
|
|
||||||
|
variables:
|
||||||
|
COMMON_BUILD_OPTIONS: --prefix=/usr --sysconfdir=/etc --localstatedir=/var --mandir=/usr/share/man --libdir=/usr/lib64 -Dpam-prefix=/etc -Drun-dir=/run/gdm -Dudev-dir=/lib/udev/rules.d -Ddefault-path=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin -Dprofiling=true -Dplymouth=enabled -Dselinux=enabled
|
||||||
|
MESON_BUILD_DIR: build
|
||||||
|
TARBALL_ARTIFACT_PATH: "${MESON_BUILD_DIR}/meson-dist/${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.xz"
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- prepare
|
||||||
|
- build
|
||||||
|
- release
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
# Allow to switch from branch pipelines to MR pipelines seamlessly
|
||||||
|
# https://docs.gitlab.com/ee/ci/jobs/job_control.html#avoid-duplicate-pipelines
|
||||||
|
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
|
||||||
|
when: never
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
# Don't trigger a branch pipeline if there is an open MR
|
||||||
|
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||||
|
when: never
|
||||||
|
- if: '$CI_COMMIT_BRANCH'
|
||||||
|
- if: '$CI_COMMIT_TAG'
|
||||||
|
|
||||||
|
.gdm.fedora:
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_VERSION: 41
|
||||||
|
FDO_DISTRIBUTION_TAG: '2025-02-06.0'
|
||||||
|
FDO_DISTRIBUTION_PACKAGES:
|
||||||
|
accountsservice-devel
|
||||||
|
audit-libs-devel
|
||||||
|
check-devel
|
||||||
|
dconf
|
||||||
|
desktop-file-utils
|
||||||
|
gettext-devel
|
||||||
|
git
|
||||||
|
gobject-introspection-devel
|
||||||
|
iso-codes-devel
|
||||||
|
itstool
|
||||||
|
json-glib-devel
|
||||||
|
keyutils-libs-devel
|
||||||
|
libattr-devel
|
||||||
|
libgudev-devel
|
||||||
|
libdmx-devel
|
||||||
|
libselinux-devel
|
||||||
|
libtool
|
||||||
|
meson
|
||||||
|
nss-devel
|
||||||
|
pam-devel
|
||||||
|
plymouth-devel
|
||||||
|
redhat-rpm-config
|
||||||
|
systemd
|
||||||
|
systemd-devel
|
||||||
|
which
|
||||||
|
yelp-devel
|
||||||
|
gtk3-devel
|
||||||
|
libXau-devel
|
||||||
|
libXdmcp-devel
|
||||||
|
xorg-x11-server-Xorg
|
||||||
|
xorg-x11-server-devel
|
||||||
|
|
||||||
|
.dummy-container-build:
|
||||||
|
script:
|
||||||
|
- echo Dummy container build
|
||||||
|
|
||||||
|
build-fedora-container:
|
||||||
|
extends:
|
||||||
|
#- .fdo.container-build@fedora@x86_64
|
||||||
|
- .dummy-container-build
|
||||||
|
- .gdm.fedora
|
||||||
|
stage: prepare
|
||||||
|
rules:
|
||||||
|
- when: always
|
||||||
|
|
||||||
|
build-fedora:
|
||||||
|
extends:
|
||||||
|
- .fdo.distribution-image@fedora
|
||||||
|
- .gdm.fedora
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- meson setup ${MESON_BUILD_DIR} ${COMMON_BUILD_OPTIONS}
|
||||||
|
- meson compile -C ${MESON_BUILD_DIR}
|
||||||
|
- meson install -C ${MESON_BUILD_DIR}
|
||||||
|
- meson dist -C ${MESON_BUILD_DIR}
|
||||||
|
- meson test -C ${MESON_BUILD_DIR}
|
||||||
|
rules:
|
||||||
|
- when: always
|
||||||
|
artifacts:
|
||||||
|
name: "${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- "${TARBALL_ARTIFACT_PATH}"
|
||||||
|
|
||||||
|
build-fedora-wayland:
|
||||||
|
extends:
|
||||||
|
- .fdo.distribution-image@fedora
|
||||||
|
- .gdm.fedora
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- meson setup ${MESON_BUILD_DIR} ${COMMON_BUILD_OPTIONS} -Dx11-support=false
|
||||||
|
- meson compile -C ${MESON_BUILD_DIR}
|
||||||
|
- meson install -C ${MESON_BUILD_DIR}
|
||||||
|
- meson dist -C ${MESON_BUILD_DIR}
|
||||||
|
- meson test -C ${MESON_BUILD_DIR}
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_TAG == null
|
2
AUTHORS
Normal file
2
AUTHORS
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
William Jon McCann <mccann@jhu.edu>
|
||||||
|
Ray Strode <rstrode@redhat.com>
|
339
COPYING
Normal file
339
COPYING
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
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 Lesser 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.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 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 Lesser General
|
||||||
|
Public License instead of this License.
|
46
HACKING
Normal file
46
HACKING
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
Coding Style
|
||||||
|
============
|
||||||
|
|
||||||
|
* Follow the coding style already used.
|
||||||
|
* Trailing whitespace is not allowed.
|
||||||
|
* Use spaces (not tabs) for indentation.
|
||||||
|
* Brace on same line as block statement.
|
||||||
|
* Use braces on all blocks (even single line blocks).
|
||||||
|
* Code must conform to C89/C90 (ANSI/ISO C) (ie. no C99).
|
||||||
|
* Spaces between functions and arguments, or macros and arguments.
|
||||||
|
* Spaces before and after most binary operators.
|
||||||
|
* Spaces after most unary operators (including a comma).
|
||||||
|
* Return value on line before function definition.
|
||||||
|
* Brace on line after function definition.
|
||||||
|
* Do not initialize local variables in their declarations.
|
||||||
|
* Line up function arguments in declarations.
|
||||||
|
* One variable declaration per line.
|
||||||
|
* Line up variable names in declarations.
|
||||||
|
* Limit the use of function prototypes by defining functions
|
||||||
|
in the file before they are used.
|
||||||
|
* Whenever possible conditional expressions should not have side
|
||||||
|
effects (eg. don't set a value or call a function in an if
|
||||||
|
statement).
|
||||||
|
* '*' goes with variable not type, when declaring a pointer.
|
||||||
|
* Function arguments follow the function call on the same line, and if
|
||||||
|
lengthy are (where possible) wrapped to the column of the first brace.
|
||||||
|
* Always compare pointers with NULL instead of using "!".
|
||||||
|
* If you make a non-trivial and copyrightable change to a file
|
||||||
|
be sure to add your name to the copyright information at the
|
||||||
|
beginning of the file.
|
||||||
|
* Use gtk-doc style comments on public functions whenever possible.
|
||||||
|
* In most cases, don't abbreviate words in function and variable names.
|
||||||
|
* Function names are lowercase, words separated by underscores.
|
||||||
|
* Macros and enums are all uppercase, words seperated by
|
||||||
|
underscores.
|
||||||
|
* Types are all words capitalized, no separators between words.
|
||||||
|
|
||||||
|
* Don't use gchar. "char" is just fine.
|
||||||
|
* Public functions should check input using g_return_if_fail.
|
||||||
|
* Private functions should check input using g_assert.
|
||||||
|
* Handle the default case in switch statements with
|
||||||
|
a warning or g_assert_not_reached.
|
||||||
|
* Prefer glib functions over native ones when available.
|
||||||
|
* Use glib string handling functions when possible.
|
||||||
|
|
||||||
|
* When in doubt copy the style of the rest of the file.
|
3
MAINTAINERS
Normal file
3
MAINTAINERS
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Ray Strode
|
||||||
|
E-mail: rstrode@redhat.com
|
||||||
|
Userid: halfline
|
657
NEWS
Normal file
657
NEWS
Normal file
|
@ -0,0 +1,657 @@
|
||||||
|
=======
|
||||||
|
Version 48.0
|
||||||
|
=======
|
||||||
|
- Allow changing global network settings
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
=======
|
||||||
|
48.beta
|
||||||
|
=======
|
||||||
|
- Don't require Xwayland if wayland-only
|
||||||
|
- Fix pam_syslog detection
|
||||||
|
- Fix Solaris build
|
||||||
|
- Fix udev rules for disabling wayland
|
||||||
|
- Add 'banner-message-path' and '-source' settings
|
||||||
|
|
||||||
|
==========
|
||||||
|
Version 47
|
||||||
|
==========
|
||||||
|
- Fix X11 support
|
||||||
|
|
||||||
|
=============
|
||||||
|
Version 47.rc
|
||||||
|
=============
|
||||||
|
- Make X11 support optional
|
||||||
|
- Support logind secure attention key
|
||||||
|
- Drop gdm-screenshot
|
||||||
|
- Don't hardcode g-r-d in dbus policy
|
||||||
|
- Fix numeric local address resolution
|
||||||
|
- Docs updates
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 47.alpha
|
||||||
|
================
|
||||||
|
- Support for gnome-remote-desktop persistent sessions
|
||||||
|
- Misc changes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 46.0
|
||||||
|
============
|
||||||
|
- PAM improvements
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
=============
|
||||||
|
Version 46.rc
|
||||||
|
=============
|
||||||
|
- Support for killing conflicting sessions at login time.
|
||||||
|
- XDMCP fix
|
||||||
|
- Use wayland by default on certain server chips
|
||||||
|
- Fix pam extension size computation
|
||||||
|
- Introspection fix
|
||||||
|
- Fix for homed users
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 46.alpha
|
||||||
|
================
|
||||||
|
- Support remote login from gnome-remote-desktop (and hopefuly nicedcv in the future)
|
||||||
|
- Support new JSON pam extension
|
||||||
|
- Fix build with user-display-server=false
|
||||||
|
- Minor clean ups
|
||||||
|
- Move private D-Bus sockets to private directory
|
||||||
|
- Build goo fixes
|
||||||
|
- Warning fixes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 45.0.1
|
||||||
|
==============
|
||||||
|
- Fix for the crasher fix
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 45.0
|
||||||
|
============
|
||||||
|
- Crasher fix
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 45.beta
|
||||||
|
===============
|
||||||
|
- A ton of small code clean ups and small leak fixes
|
||||||
|
- Set gnome-initial-setup dconf profile
|
||||||
|
- Honor settings configured with a template in AccountsService
|
||||||
|
- Crash fix from stray udev events
|
||||||
|
- VT handling fixes
|
||||||
|
- Work better in presence of simpledrm
|
||||||
|
- wayland multi-seat support
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 44.0
|
||||||
|
============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
=============
|
||||||
|
Version 44.rc
|
||||||
|
=============
|
||||||
|
- Lots of code clean ups
|
||||||
|
- Fix detection of virt on efi setups
|
||||||
|
- Fix btmp accounting on failed logins
|
||||||
|
- Ensure pam_close_session is called even if worker is killed
|
||||||
|
- PAM config update on Arch
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 43.0
|
||||||
|
============
|
||||||
|
- Drop vestigial code
|
||||||
|
- Fixes in GPU detection
|
||||||
|
- use _GNU_SOURCE again to avoid compile warning
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 42.0
|
||||||
|
============
|
||||||
|
- Work better on nvidia
|
||||||
|
- Look in DATADIR for launch environment data files
|
||||||
|
- PAM updates on exherbo
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 41.3
|
||||||
|
============
|
||||||
|
- Juggle Xorg's -listen/-nolisten command line change better
|
||||||
|
- Fix session type selection
|
||||||
|
- Fix crash
|
||||||
|
- Drop vestigial gdm-pin service
|
||||||
|
- XDMCP fixes
|
||||||
|
- Wayland nvidia udev updates
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
============
|
||||||
|
Version 41.0
|
||||||
|
============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 41.rc1
|
||||||
|
==============
|
||||||
|
- Fix fallback to Xorg at login screen
|
||||||
|
- Fix SessionType in AccountService user config
|
||||||
|
- Reuse VT on log out
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 41.alpha
|
||||||
|
================
|
||||||
|
- Allow user session to be Wayland even when login screen is Xorg
|
||||||
|
- Allow wayland user sessions for single GPU vendor nvidia machines
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==========
|
||||||
|
Version 40
|
||||||
|
==========
|
||||||
|
- 100% CPU fix
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 40.rc
|
||||||
|
================
|
||||||
|
- Fingerprint auth fixes
|
||||||
|
- Fix timeout handling for graphics bringup
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 40.beta
|
||||||
|
================
|
||||||
|
- xinit script improvements
|
||||||
|
- Build goo fixes
|
||||||
|
- Support systems that boot before the graphics subsystem fully loads
|
||||||
|
- Don't overwrite PATH set by user
|
||||||
|
- Generalize gdm-disable-wayland into new gdm-runtime-config tool
|
||||||
|
- Fail hard if accountsservice fails
|
||||||
|
- PAM integration improvements
|
||||||
|
- Leak fixes
|
||||||
|
- Stop using deprecated systemd functions
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 3.38.2.1
|
||||||
|
================
|
||||||
|
- Address autologin unlock bug issue (CVE-2020-27837)
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.38.2
|
||||||
|
==============
|
||||||
|
- Fix localization bug to prevented translated messages from showing up
|
||||||
|
- Deal more appropriately with broken accountsservice
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.38.1
|
||||||
|
==============
|
||||||
|
- Fix bug leading to users /etc/gdm/custom.conf getting overwritten on nvidia systems.
|
||||||
|
- Fix typo in comment
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.38.0
|
||||||
|
==============
|
||||||
|
- Crasher fix
|
||||||
|
- build goo updates
|
||||||
|
- systemd unit file improvements
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.37.90
|
||||||
|
===============
|
||||||
|
- Updates to systemd integration
|
||||||
|
- deprecation fixes
|
||||||
|
- Support killling X on login even when wayland support is disabled
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.37.3
|
||||||
|
==============
|
||||||
|
- PAM file updates for archlinux
|
||||||
|
- User switching fix
|
||||||
|
- Don't keep login screen running in background on Xorg
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.37.1
|
||||||
|
==============
|
||||||
|
- Switch from autogoo to meson
|
||||||
|
- Fixes for when GDM isn't started on its configured initial VT
|
||||||
|
- Don't hardcode path to plymouth
|
||||||
|
- keyutils has a .pc file so use it
|
||||||
|
- Enable wayland on cirrus
|
||||||
|
- Chrome remote desktop fix
|
||||||
|
- Always use separate session bus for greeter sessions
|
||||||
|
This runs dbus-run-session, so the binary needs to be available
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.34.1
|
||||||
|
==============
|
||||||
|
- De-duplicate sessions on pure Xorg too
|
||||||
|
- Fix fast user switching by assuming the login screen VT is always the initial
|
||||||
|
one
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.34.0
|
||||||
|
==============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.33.92
|
||||||
|
===============
|
||||||
|
- Fix typo in debug message
|
||||||
|
- Revert vt changing fix, because it exposes logind bug and it wasn't quite right anyway
|
||||||
|
- Ensure login screen gets reaped when user switching
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.33.90
|
||||||
|
===============
|
||||||
|
- Update for changes to gnome-settings-daemon
|
||||||
|
- initial-setup permissions fix
|
||||||
|
- allow users to set PATH from ~/.config/environmet
|
||||||
|
- support systemd user sessions
|
||||||
|
- misc warning fixes
|
||||||
|
- leak fix in libgdm
|
||||||
|
- vt changing fix
|
||||||
|
- drop some deprecations
|
||||||
|
- drop unused icons
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.33.4
|
||||||
|
==============
|
||||||
|
- Fix session search directories
|
||||||
|
- Kill user sessions when stopping gdm
|
||||||
|
- Add way for sessions to register when they successfully started
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.32.0
|
||||||
|
==============
|
||||||
|
- No updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.31.91
|
||||||
|
===============
|
||||||
|
- Screen lock bypass fix (when timed login is enabled) (CVE-2019-3825)
|
||||||
|
- PAM file updates
|
||||||
|
- Improved debug logging
|
||||||
|
- Keyboard layout fixes
|
||||||
|
- Display foreach handling
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.31.4
|
||||||
|
==============
|
||||||
|
- DOAP file fixes
|
||||||
|
- misc code clean ups
|
||||||
|
- filter out duplicates from session list
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.30.2
|
||||||
|
==============
|
||||||
|
- Fix autologin crash
|
||||||
|
- Unlock keyring again on autologin with newerish systemds
|
||||||
|
- Fix initial-setup
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.30.1
|
||||||
|
==============
|
||||||
|
- make udev rule configurable
|
||||||
|
- follow up fixes dealing with login screen reaping from two releases ago
|
||||||
|
- disable wayland on proprietary nvidia machines for now
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.30.0
|
||||||
|
==============
|
||||||
|
- build fixes
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.29.92
|
||||||
|
===============
|
||||||
|
- search for sessions in XDG_DATA_DIRS
|
||||||
|
- blacklist some more wayland unfriendly hardware
|
||||||
|
- initial setup fix
|
||||||
|
- flicker fix
|
||||||
|
- misc bug fixes
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.29.91
|
||||||
|
===============
|
||||||
|
- CVE-2018-14424 - double free fix
|
||||||
|
- follow up fixes dealing with login screen reaping form last release
|
||||||
|
- add more debug logging
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.29.90
|
||||||
|
===============
|
||||||
|
- display wayland on certain server machines
|
||||||
|
- lifecycle fixes to libgdm/GdmClient
|
||||||
|
- drop intltool
|
||||||
|
- build goo clean ups
|
||||||
|
- kill login screen when not in use
|
||||||
|
- clean up stale utmp entries
|
||||||
|
- misc fixes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.29.1
|
||||||
|
==============
|
||||||
|
- Reference counting fixes for GdmClient- ensure plymouth is quit properly even when local greeter is disabled
|
||||||
|
- make sure GDM doesn't hang when called with unknown command line arguments
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.28.0
|
||||||
|
==============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.27.92
|
||||||
|
===============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.27.91
|
||||||
|
===============
|
||||||
|
- Ensure default session for user gets reported to login screen up front
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.27.90
|
||||||
|
===============
|
||||||
|
- Add support for configuration from /run
|
||||||
|
- Add udev rule to disable wayland with cirrus
|
||||||
|
- Remove obsolete stuff about Xnest from configure
|
||||||
|
- Adjust for g-s-d plugin removal
|
||||||
|
- segfault fix in error condition for session wrappers
|
||||||
|
- misc warning fixes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.27.4
|
||||||
|
==============
|
||||||
|
- Fix for invalid DISPLAY/XAUTHORITY in session scripts
|
||||||
|
- Fix for keyring integration on multidisk systems
|
||||||
|
- Set GROUP environment variable
|
||||||
|
- Deprecation fixes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.27.3
|
||||||
|
==============
|
||||||
|
- don't call gdm_session_defaults_changed from setup
|
||||||
|
- Add dependency to .pc file
|
||||||
|
- code clean ups
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.26.1
|
||||||
|
==============
|
||||||
|
- Check for Xwayland before agreeing to do wayland
|
||||||
|
- misc wayland fixes
|
||||||
|
- xdmcp fixes
|
||||||
|
- minor clean ups
|
||||||
|
- allow gnome initial-setup to be forced from kernel command line
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.26.0
|
||||||
|
==============
|
||||||
|
- Fix for unauthenticated unlock when autologin is enabled (CVE-2017-12164)
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.25.92
|
||||||
|
===============
|
||||||
|
- Fix for going to normal mode after classic
|
||||||
|
- crasher fix when user switching
|
||||||
|
- make sure reauthentication is run in right context
|
||||||
|
- send hangup signal to gdm when systemctl request reload
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
=================
|
||||||
|
Version 3.25.90.1
|
||||||
|
=================
|
||||||
|
- Fix breakage in greeter and initial setup
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.25.90
|
||||||
|
===============
|
||||||
|
- Fix for going to normal mode after classic
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 3.25.4.1
|
||||||
|
================
|
||||||
|
- brown bag release to fix conflict with latest g-s-d release
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.25.4
|
||||||
|
===============
|
||||||
|
- wayland w/ --disable-user-display-server fix
|
||||||
|
- Make login screen session separate from user session again
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.25.3
|
||||||
|
===============
|
||||||
|
- crasher fix
|
||||||
|
- x11/wayland selection fix
|
||||||
|
- greeter lifecycle fix
|
||||||
|
- systemd unit installation fix
|
||||||
|
- drop lock down of non-existent setting
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.24.1
|
||||||
|
===============
|
||||||
|
- Don't set DCONF_PROFILE for gnome-initial-setup
|
||||||
|
- Remove deprecated a11y keys
|
||||||
|
- autologin fixes
|
||||||
|
- xdmcp fixes
|
||||||
|
- user switching fixes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.24.0
|
||||||
|
===============
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.23.92
|
||||||
|
===============
|
||||||
|
- Be more robust against misconfigured autologin systems
|
||||||
|
|
||||||
|
=================
|
||||||
|
Version 3.23.91.1
|
||||||
|
=================
|
||||||
|
- Fix regression in wayland fallback code
|
||||||
|
- Fix for headless sessions
|
||||||
|
- Change around how PostLogin/PostSession scripts are run
|
||||||
|
- Fix XDMCP in network environments with poor network resolution
|
||||||
|
- Don't try to user switch with XDMCP
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.23.91
|
||||||
|
===============
|
||||||
|
- Small fix to environment variable importing
|
||||||
|
- Add configure knob to turn off user X server
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.23.4
|
||||||
|
==============
|
||||||
|
- Make X11DisplayName property accurate
|
||||||
|
- Fix bug that forced wayland on second logins even if user didn't pick it
|
||||||
|
- kill clients from display on logout (multiseat and xdmcp only)
|
||||||
|
- send hangup to process group when session exits
|
||||||
|
- allow specifying pam_gdm install location to configure
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.22.1
|
||||||
|
==============
|
||||||
|
- Fix wayland login after Xorg logout for a user
|
||||||
|
- Prefer /usr/bin/X to /usr/bin/Xorg
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.22.0
|
||||||
|
==============
|
||||||
|
- autologin fixes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.21.91
|
||||||
|
===============
|
||||||
|
- fix autologin on non-LUKS systems
|
||||||
|
- import environment from systemd user manager
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.21.90
|
||||||
|
===============
|
||||||
|
- Use LUKS password for to unlock gnome-keyring at login (when autologin is enabled)
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.21.4
|
||||||
|
==============
|
||||||
|
- Small crasher fix
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.21.3
|
||||||
|
==============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.21.2
|
||||||
|
==============
|
||||||
|
- Import DISPLAY into user bus
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.20.1
|
||||||
|
==============
|
||||||
|
- Fix passwordless logins on Debian/Ubuntu
|
||||||
|
- Don't allow passwordless XDMCP logins
|
||||||
|
- Fix redhat pam configuration
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.20.0
|
||||||
|
==============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.19.92
|
||||||
|
===============
|
||||||
|
- leak fix
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.19.91
|
||||||
|
===============
|
||||||
|
- Fix log output
|
||||||
|
- Fix timed login
|
||||||
|
- Fix openembedded pam configuration
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.19.90
|
||||||
|
===============
|
||||||
|
- Better build goo output
|
||||||
|
- Support dbus user bus better
|
||||||
|
- Fix bug that prevents wayland sessions, from being wayland sometimes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 3.19.4.1
|
||||||
|
================
|
||||||
|
- Fix crasher introduced in 3.19.4
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.19.4
|
||||||
|
==============
|
||||||
|
- Don't override PAM message for password change
|
||||||
|
- Disable GVFS when we don't need it
|
||||||
|
- Fail better when no sessions are installed
|
||||||
|
- Support gnome-session in different PREFIX than GDM
|
||||||
|
- doc updates
|
||||||
|
- ensure unlock screen gets told when verification completes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.19.2
|
||||||
|
==============
|
||||||
|
- Get rid of "custom" session
|
||||||
|
- Separate X sessions and Wayland sessions
|
||||||
|
- Hide Wayland sessions if the login screen is on X
|
||||||
|
- Pass session mode to the shell via environment
|
||||||
|
- Rename gnome-wayland session to gnome
|
||||||
|
- Use -listen instead of -nolisten for new Xorg
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.18.0
|
||||||
|
==============
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.17.92
|
||||||
|
===============
|
||||||
|
- Fix log out after autologin
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
===============
|
||||||
|
Version 3.17.90
|
||||||
|
===============
|
||||||
|
- Fix GDM_LANG corruption that sometimes fails login
|
||||||
|
- Rework wtmp handling
|
||||||
|
- Code clean ups
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.17.4
|
||||||
|
==============
|
||||||
|
- Fixes to handle gdm restarts better
|
||||||
|
- Crasher fix on logout of wayland sessoin
|
||||||
|
- systemd build updates
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
================
|
||||||
|
Version 3.17.3.1
|
||||||
|
================
|
||||||
|
- Ship systemd unit file (woops)
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.17.3
|
||||||
|
==============
|
||||||
|
- Support env.d directory for manipulating session environment
|
||||||
|
- Drop ConsoleKit support
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
==============
|
||||||
|
Version 3.17.2
|
||||||
|
==============
|
||||||
|
- BSD fixes
|
||||||
|
- Don't build Xsession by default
|
||||||
|
- Fix monitor hotplug segfault
|
||||||
|
- kdbus fixes
|
||||||
|
- Translation updates
|
||||||
|
|
||||||
|
For older NEWS updates, please see git.
|
42
README.md
Normal file
42
README.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
GDM - GNOME Display Manager
|
||||||
|
===========================
|
||||||
|
http://wiki.gnome.org/Projects/GDM/
|
||||||
|
|
||||||
|
The GNOME Display Manager is a system service that is responsible for
|
||||||
|
providing graphical log-ins and managing local and remote displays.
|
||||||
|
|
||||||
|
## Building and installing
|
||||||
|
To build and install GDM from source, just execute the following commands:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ meson _build
|
||||||
|
$ ninja -C _build
|
||||||
|
$ sudo ninja -C _build install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
You can browse the code, issues and more at GDM's [GitLab repository].
|
||||||
|
|
||||||
|
If you find a bug in GDM, please file an issue on the [issue tracker]. Please
|
||||||
|
try to add reproducible steps and the relevant version of GDM.
|
||||||
|
|
||||||
|
If you want to contribute functionality or bug fixes, please open a Merge
|
||||||
|
Request (MR). For more info on how to do this, see GitLab's [help pages on
|
||||||
|
MR's]. Please also follow the GDM coding style, which is documented in
|
||||||
|
`HACKING`.
|
||||||
|
|
||||||
|
If GDM is not translated in your language or you believe that the
|
||||||
|
current translation has errors, you can join one of the various translation
|
||||||
|
teams in GNOME. Translators do not commit directly to Git, but are advised to
|
||||||
|
use our separate translation infrastructure instead. More info can be found at
|
||||||
|
the [translation project wiki page].
|
||||||
|
|
||||||
|
## Licensing
|
||||||
|
GDM is licensed under the GNU General Public License v2.0. For more info, see
|
||||||
|
the `COPYING` file.
|
||||||
|
|
||||||
|
|
||||||
|
[help pages on MR's]: https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html
|
||||||
|
[GitLab repository]: https://gitlab.gnome.org/GNOME/gdm
|
||||||
|
[issue tracker]: https://gitlab.gnome.org/GNOME/gdm/issues
|
||||||
|
[translation project wiki page]: https://wiki.gnome.org/TranslationProject/
|
34
build-aux/find-x-server.sh
Executable file
34
build-aux/find-x-server.sh
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# First check with "! -h" for /usr/X11R6 and /usr/X11 since they often
|
||||||
|
# symlink to each other, and configure should use the more stable
|
||||||
|
# location (the real directory) if possible.
|
||||||
|
#
|
||||||
|
# On Solaris, the /usr/bin/Xserver script is used to decide whether to
|
||||||
|
# use Xsun or Xorg, so this is used on Solaris.
|
||||||
|
#
|
||||||
|
# When testing for /usr/X11R6, first check with "! -h" for /usr/X11R6
|
||||||
|
# and /usr/X11 since they often symlink to each other, and configure
|
||||||
|
# should use the more stable location (the real directory) if possible.
|
||||||
|
#
|
||||||
|
if test -x /usr/bin/X; then
|
||||||
|
echo "/usr/bin/X"
|
||||||
|
elif test -x /usr/X11/bin/Xserver; then
|
||||||
|
echo "/usr/X11/bin/Xserver"
|
||||||
|
elif test ! -h /usr/X11R6 -a -x /usr/X11R6/bin/X; then
|
||||||
|
echo "/usr/X11R6/bin/X"
|
||||||
|
elif test ! -h /usr/X11 -a -x /usr/X11/bin/X; then
|
||||||
|
echo "/usr/X11/bin/X"
|
||||||
|
elif test -x /usr/X11R6/bin/X; then
|
||||||
|
echo "/usr/X11R6/bin/X"
|
||||||
|
elif test -x /usr/bin/Xorg; then
|
||||||
|
echo "/usr/bin/Xorg"
|
||||||
|
elif test -x /usr/X11/bin/X; then
|
||||||
|
echo "/usr/X11/bin/X"
|
||||||
|
elif test -x /usr/openwin/bin/Xsun; then
|
||||||
|
echo "/usr/openwin/bin/Xsun"
|
||||||
|
elif test -x /opt/X11R6/bin/X; then
|
||||||
|
echo "/opt/X11R6/bin/X"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
250
chooser/chooser-main.c
Normal file
250
chooser/chooser-main.c
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
#include "gdm-log.h"
|
||||||
|
|
||||||
|
#include "gdm-chooser-session.h"
|
||||||
|
|
||||||
|
#define ACCESSIBILITY_KEY "/desktop/gnome/interface/accessibility"
|
||||||
|
|
||||||
|
static Atom AT_SPI_IOR;
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
assistive_registry_launch (void)
|
||||||
|
{
|
||||||
|
GPid pid;
|
||||||
|
GError *error;
|
||||||
|
const char *command;
|
||||||
|
char **argv;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
command = AT_SPI_REGISTRYD_DIR "/at-spi-registryd";
|
||||||
|
|
||||||
|
argv = NULL;
|
||||||
|
error = NULL;
|
||||||
|
res = g_shell_parse_argv (command, NULL, &argv, &error);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to parse command: %s", error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
res = g_spawn_async (NULL,
|
||||||
|
argv,
|
||||||
|
NULL,
|
||||||
|
G_SPAWN_SEARCH_PATH
|
||||||
|
| G_SPAWN_STDOUT_TO_DEV_NULL
|
||||||
|
| G_SPAWN_STDERR_TO_DEV_NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&pid,
|
||||||
|
&error);
|
||||||
|
g_strfreev (argv);
|
||||||
|
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to run command %s: %s", command, error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kill (pid, 0) < 0) {
|
||||||
|
g_warning ("at-spi-registryd not running");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkFilterReturn
|
||||||
|
filter_watch (GdkXEvent *xevent,
|
||||||
|
GdkEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
XEvent *xev = (XEvent *)xevent;
|
||||||
|
|
||||||
|
if (xev->xany.type == PropertyNotify
|
||||||
|
&& xev->xproperty.atom == AT_SPI_IOR) {
|
||||||
|
gtk_main_quit ();
|
||||||
|
|
||||||
|
return GDK_FILTER_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDK_FILTER_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
filter_timeout (gpointer data)
|
||||||
|
{
|
||||||
|
g_warning ("The accessibility registry was not found.");
|
||||||
|
|
||||||
|
gtk_main_quit ();
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assistive_registry_start (void)
|
||||||
|
{
|
||||||
|
GdkWindow *root;
|
||||||
|
guint tid;
|
||||||
|
|
||||||
|
root = gdk_get_default_root_window ();
|
||||||
|
|
||||||
|
if ( ! AT_SPI_IOR) {
|
||||||
|
AT_SPI_IOR = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "AT_SPI_IOR", False);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_window_set_events (root, GDK_PROPERTY_CHANGE_MASK);
|
||||||
|
|
||||||
|
if ( ! assistive_registry_launch ()) {
|
||||||
|
g_warning ("The accessibility registry could not be started.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_window_add_filter (root, filter_watch, NULL);
|
||||||
|
tid = g_timeout_add_seconds (5, filter_timeout, NULL);
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
gdk_window_remove_filter (root, filter_watch, NULL);
|
||||||
|
g_source_remove (tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
at_set_gtk_modules (void)
|
||||||
|
{
|
||||||
|
GSList *modules_list;
|
||||||
|
GSList *l;
|
||||||
|
const char *old;
|
||||||
|
char **modules;
|
||||||
|
gboolean found_gail;
|
||||||
|
gboolean found_atk_bridge;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
modules_list = NULL;
|
||||||
|
found_gail = FALSE;
|
||||||
|
found_atk_bridge = FALSE;
|
||||||
|
|
||||||
|
if ((old = g_getenv ("GTK_MODULES")) != NULL) {
|
||||||
|
modules = g_strsplit (old, ":", -1);
|
||||||
|
for (n = 0; modules[n]; n++) {
|
||||||
|
if (!strcmp (modules[n], "gail")) {
|
||||||
|
found_gail = TRUE;
|
||||||
|
} else if (!strcmp (modules[n], "atk-bridge")) {
|
||||||
|
found_atk_bridge = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
modules_list = g_slist_prepend (modules_list, modules[n]);
|
||||||
|
modules[n] = NULL;
|
||||||
|
}
|
||||||
|
g_free (modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_gail) {
|
||||||
|
modules_list = g_slist_prepend (modules_list, "gail");
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_atk_bridge) {
|
||||||
|
modules_list = g_slist_prepend (modules_list, "atk-bridge");
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
|
||||||
|
modules = g_new (char *, n + 1);
|
||||||
|
modules[n--] = NULL;
|
||||||
|
for (l = modules_list; l; l = l->next) {
|
||||||
|
modules[n--] = g_strdup (l->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_setenv ("GTK_MODULES", g_strjoinv (":", modules), TRUE);
|
||||||
|
g_strfreev (modules);
|
||||||
|
g_slist_free (modules_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_a11y (void)
|
||||||
|
{
|
||||||
|
assistive_registry_start ();
|
||||||
|
at_set_gtk_modules ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GdmChooserSession *session;
|
||||||
|
gboolean res;
|
||||||
|
GError *error;
|
||||||
|
|
||||||
|
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||||
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||||
|
textdomain (GETTEXT_PACKAGE);
|
||||||
|
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
|
gdm_log_init ();
|
||||||
|
gdm_log_set_debug (TRUE);
|
||||||
|
|
||||||
|
g_debug ("Chooser for display %s xauthority:%s",
|
||||||
|
g_getenv ("DISPLAY"),
|
||||||
|
g_getenv ("XAUTHORITY"));
|
||||||
|
|
||||||
|
gdk_init (&argc, &argv);
|
||||||
|
|
||||||
|
load_a11y ();
|
||||||
|
|
||||||
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
|
session = gdm_chooser_session_new ();
|
||||||
|
if (session == NULL) {
|
||||||
|
g_critical ("Unable to create chooser session");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
res = gdm_chooser_session_start (session, &error);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to start chooser session: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
if (session != NULL) {
|
||||||
|
g_object_unref (session);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
252
chooser/gdm-chooser-host.c
Normal file
252
chooser/gdm-chooser-host.c
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-address.h"
|
||||||
|
#include "gdm-chooser-host.h"
|
||||||
|
|
||||||
|
struct _GdmChooserHost
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
GdmAddress *address;
|
||||||
|
char *description;
|
||||||
|
GdmChooserHostKind kind;
|
||||||
|
gboolean willing;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_ADDRESS,
|
||||||
|
PROP_DESCRIPTION,
|
||||||
|
PROP_KIND,
|
||||||
|
PROP_WILLING,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_chooser_host_class_init (GdmChooserHostClass *klass);
|
||||||
|
static void gdm_chooser_host_init (GdmChooserHost *chooser_host);
|
||||||
|
static void gdm_chooser_host_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmChooserHost, gdm_chooser_host, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
GdmAddress *
|
||||||
|
gdm_chooser_host_get_address (GdmChooserHost *host)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_CHOOSER_HOST (host), NULL);
|
||||||
|
|
||||||
|
return host->address;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gdm_chooser_host_get_description (GdmChooserHost *host)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_CHOOSER_HOST (host), NULL);
|
||||||
|
|
||||||
|
return host->description;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmChooserHostKind
|
||||||
|
gdm_chooser_host_get_kind (GdmChooserHost *host)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_CHOOSER_HOST (host), 0);
|
||||||
|
|
||||||
|
return host->kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_chooser_host_get_willing (GdmChooserHost *host)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_CHOOSER_HOST (host), FALSE);
|
||||||
|
|
||||||
|
return host->willing;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_chooser_host_set_address (GdmChooserHost *host,
|
||||||
|
GdmAddress *address)
|
||||||
|
{
|
||||||
|
if (host->address != NULL) {
|
||||||
|
gdm_address_free (host->address);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (address != NULL);
|
||||||
|
|
||||||
|
gdm_address_debug (address);
|
||||||
|
host->address = gdm_address_copy (address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_chooser_host_set_description (GdmChooserHost *host,
|
||||||
|
const char *description)
|
||||||
|
{
|
||||||
|
g_free (host->description);
|
||||||
|
host->description = g_strdup (description);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_chooser_host_set_kind (GdmChooserHost *host,
|
||||||
|
int kind)
|
||||||
|
{
|
||||||
|
if (host->kind != kind) {
|
||||||
|
host->kind = kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_chooser_host_set_willing (GdmChooserHost *host,
|
||||||
|
gboolean willing)
|
||||||
|
{
|
||||||
|
if (host->willing != willing) {
|
||||||
|
host->willing = willing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_host_set_property (GObject *object,
|
||||||
|
guint param_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmChooserHost *host;
|
||||||
|
|
||||||
|
host = GDM_CHOOSER_HOST (object);
|
||||||
|
|
||||||
|
switch (param_id) {
|
||||||
|
case PROP_ADDRESS:
|
||||||
|
_gdm_chooser_host_set_address (host, g_value_get_boxed (value));
|
||||||
|
break;
|
||||||
|
case PROP_DESCRIPTION:
|
||||||
|
_gdm_chooser_host_set_description (host, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_KIND:
|
||||||
|
_gdm_chooser_host_set_kind (host, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
case PROP_WILLING:
|
||||||
|
_gdm_chooser_host_set_willing (host, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_host_get_property (GObject *object,
|
||||||
|
guint param_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmChooserHost *host;
|
||||||
|
|
||||||
|
host = GDM_CHOOSER_HOST (object);
|
||||||
|
|
||||||
|
switch (param_id) {
|
||||||
|
case PROP_ADDRESS:
|
||||||
|
g_value_set_boxed (value, host->address);
|
||||||
|
break;
|
||||||
|
case PROP_DESCRIPTION:
|
||||||
|
g_value_set_string (value, host->description);
|
||||||
|
break;
|
||||||
|
case PROP_KIND:
|
||||||
|
g_value_set_int (value, host->kind);
|
||||||
|
break;
|
||||||
|
case PROP_WILLING:
|
||||||
|
g_value_set_boolean (value, host->willing);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_host_class_init (GdmChooserHostClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->set_property = gdm_chooser_host_set_property;
|
||||||
|
object_class->get_property = gdm_chooser_host_get_property;
|
||||||
|
object_class->finalize = gdm_chooser_host_finalize;
|
||||||
|
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_ADDRESS,
|
||||||
|
g_param_spec_boxed ("address",
|
||||||
|
"address",
|
||||||
|
"address",
|
||||||
|
GDM_TYPE_ADDRESS,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_DESCRIPTION,
|
||||||
|
g_param_spec_string ("description",
|
||||||
|
"description",
|
||||||
|
"description",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_KIND,
|
||||||
|
g_param_spec_int ("kind",
|
||||||
|
"kind",
|
||||||
|
"kind",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_WILLING,
|
||||||
|
g_param_spec_boolean ("willing",
|
||||||
|
"willing",
|
||||||
|
"willing",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_host_init (GdmChooserHost *widget)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_host_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmChooserHost *host;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_CHOOSER_HOST (object));
|
||||||
|
|
||||||
|
host = GDM_CHOOSER_HOST (object);
|
||||||
|
|
||||||
|
g_free (host->description);
|
||||||
|
gdm_address_free (host->address);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_chooser_host_parent_class)->finalize (object);
|
||||||
|
}
|
44
chooser/gdm-chooser-host.h
Normal file
44
chooser/gdm-chooser-host.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_CHOOSER_HOST__
|
||||||
|
#define __GDM_CHOOSER_HOST__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gdm-address.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_CHOOSER_HOST (gdm_chooser_host_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmChooserHost, gdm_chooser_host, GDM, CHOOSER_HOST, GObject)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GDM_CHOOSER_HOST_KIND_XDMCP = 1 << 0,
|
||||||
|
} GdmChooserHostKind;
|
||||||
|
|
||||||
|
#define GDM_CHOOSER_HOST_KIND_MASK_ALL (GDM_CHOOSER_HOST_KIND_XDMCP)
|
||||||
|
|
||||||
|
const char *gdm_chooser_host_get_description (GdmChooserHost *chooser_host);
|
||||||
|
GdmAddress * gdm_chooser_host_get_address (GdmChooserHost *chooser_host);
|
||||||
|
gboolean gdm_chooser_host_get_willing (GdmChooserHost *chooser_host);
|
||||||
|
GdmChooserHostKind gdm_chooser_host_get_kind (GdmChooserHost *chooser_host);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
337
chooser/gdm-chooser-session.c
Normal file
337
chooser/gdm-chooser-session.c
Normal file
|
@ -0,0 +1,337 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-chooser-session.h"
|
||||||
|
#include "gdm-client.h"
|
||||||
|
|
||||||
|
#include "gdm-host-chooser-dialog.h"
|
||||||
|
|
||||||
|
struct _GdmChooserSession
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
GdmClient *client;
|
||||||
|
GdmRemoteGreeter *remote_greeter;
|
||||||
|
GdmChooser *chooser;
|
||||||
|
GtkWidget *chooser_dialog;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_chooser_session_class_init (GdmChooserSessionClass *klass);
|
||||||
|
static void gdm_chooser_session_init (GdmChooserSession *chooser_session);
|
||||||
|
static void gdm_chooser_session_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmChooserSession, gdm_chooser_session, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static gpointer session_object = NULL;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
launch_compiz (GdmChooserSession *session)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_debug ("GdmChooserSession: Launching compiz");
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
g_spawn_command_line_async ("gtk-window-decorator --replace", &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("Error starting WM: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
g_spawn_command_line_async ("compiz --replace", &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("Error starting WM: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
/* FIXME: should try to detect if it actually works */
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
launch_metacity (GdmChooserSession *session)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_debug ("GdmChooserSession: Launching metacity");
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
g_spawn_command_line_async ("metacity --replace", &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("Error starting WM: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_window_manager (GdmChooserSession *session)
|
||||||
|
{
|
||||||
|
if (! launch_metacity (session)) {
|
||||||
|
launch_compiz (session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
start_settings_daemon (GdmChooserSession *session)
|
||||||
|
{
|
||||||
|
GError *error;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_debug ("GdmChooserSession: Launching settings daemon");
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
g_spawn_command_line_async (GNOME_SETTINGS_DAEMON_DIR "/gnome-settings-daemon", &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("Error starting settings daemon: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_dialog_response (GtkDialog *dialog,
|
||||||
|
int response_id,
|
||||||
|
GdmChooserSession *session)
|
||||||
|
{
|
||||||
|
GdmChooserHost *host;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
host = NULL;
|
||||||
|
switch (response_id) {
|
||||||
|
case GTK_RESPONSE_OK:
|
||||||
|
host = gdm_host_chooser_dialog_get_host (GDM_HOST_CHOOSER_DIALOG (dialog));
|
||||||
|
case GTK_RESPONSE_NONE:
|
||||||
|
/* delete event */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host != NULL) {
|
||||||
|
char *hostname;
|
||||||
|
|
||||||
|
/* only support XDMCP hosts in remote chooser */
|
||||||
|
g_assert (gdm_chooser_host_get_kind (host) == GDM_CHOOSER_HOST_KIND_XDMCP);
|
||||||
|
|
||||||
|
hostname = NULL;
|
||||||
|
gdm_address_get_hostname (gdm_chooser_host_get_address (host), &hostname);
|
||||||
|
/* FIXME: fall back to numerical address? */
|
||||||
|
if (hostname != NULL) {
|
||||||
|
g_debug ("GdmChooserSession: Selected hostname '%s'", hostname);
|
||||||
|
gdm_chooser_call_select_hostname_sync (session->chooser,
|
||||||
|
hostname,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("GdmChooserSession: %s", error->message);
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
g_free (hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdm_remote_greeter_call_disconnect_sync (session->remote_greeter,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("GdmChooserSession: disconnect failed: %s", error->message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_chooser_session_start (GdmChooserSession *session,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_CHOOSER_SESSION (session), FALSE);
|
||||||
|
|
||||||
|
session->remote_greeter = gdm_client_get_remote_greeter_sync (session->client,
|
||||||
|
NULL,
|
||||||
|
error);
|
||||||
|
if (session->remote_greeter == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
session->chooser = gdm_client_get_chooser_sync (session->client,
|
||||||
|
NULL,
|
||||||
|
error);
|
||||||
|
if (session->chooser == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_settings_daemon (session);
|
||||||
|
start_window_manager (session);
|
||||||
|
|
||||||
|
/* Only support XDMCP on remote choosers */
|
||||||
|
session->chooser_dialog = gdm_host_chooser_dialog_new (GDM_CHOOSER_HOST_KIND_XDMCP);
|
||||||
|
g_signal_connect (session->chooser_dialog,
|
||||||
|
"response",
|
||||||
|
G_CALLBACK (on_dialog_response),
|
||||||
|
session);
|
||||||
|
gtk_widget_show (session->chooser_dialog);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_chooser_session_stop (GdmChooserSession *session)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_CHOOSER_SESSION (session));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_session_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
|
||||||
|
gdm_chooser_session_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 *
|
||||||
|
gdm_chooser_session_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmChooserSession *chooser_session;
|
||||||
|
|
||||||
|
chooser_session = GDM_CHOOSER_SESSION (G_OBJECT_CLASS (gdm_chooser_session_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
return G_OBJECT (chooser_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_session_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
g_debug ("GdmChooserSession: Disposing chooser_session");
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_chooser_session_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_session_class_init (GdmChooserSessionClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_chooser_session_get_property;
|
||||||
|
object_class->set_property = gdm_chooser_session_set_property;
|
||||||
|
object_class->constructor = gdm_chooser_session_constructor;
|
||||||
|
object_class->dispose = gdm_chooser_session_dispose;
|
||||||
|
object_class->finalize = gdm_chooser_session_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_session_init (GdmChooserSession *session)
|
||||||
|
{
|
||||||
|
session->client = gdm_client_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_chooser_session_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmChooserSession *chooser_session;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_CHOOSER_SESSION (object));
|
||||||
|
|
||||||
|
chooser_session = GDM_CHOOSER_SESSION (object);
|
||||||
|
|
||||||
|
g_return_if_fail (chooser_session != NULL);
|
||||||
|
|
||||||
|
g_clear_object (&chooser_session->chooser);
|
||||||
|
g_clear_object (&chooser_session->remote_greeter);
|
||||||
|
g_clear_object (&chooser_session->client);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_chooser_session_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmChooserSession *
|
||||||
|
gdm_chooser_session_new (void)
|
||||||
|
{
|
||||||
|
if (session_object != NULL) {
|
||||||
|
g_object_ref (session_object);
|
||||||
|
} else {
|
||||||
|
session_object = g_object_new (GDM_TYPE_CHOOSER_SESSION, NULL);
|
||||||
|
g_object_add_weak_pointer (session_object,
|
||||||
|
(gpointer *) &session_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDM_CHOOSER_SESSION (session_object);
|
||||||
|
}
|
39
chooser/gdm-chooser-session.h
Normal file
39
chooser/gdm-chooser-session.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_CHOOSER_SESSION_H
|
||||||
|
#define __GDM_CHOOSER_SESSION_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_CHOOSER_SESSION (gdm_chooser_session_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmChooserSession, gdm_chooser_session, GDM, CHOOSER_SESSION, GObject)
|
||||||
|
|
||||||
|
GdmChooserSession * gdm_chooser_session_new (void);
|
||||||
|
|
||||||
|
gboolean gdm_chooser_session_start (GdmChooserSession *session,
|
||||||
|
GError **error);
|
||||||
|
void gdm_chooser_session_stop (GdmChooserSession *session);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_CHOOSER_SESSION_H */
|
203
chooser/gdm-host-chooser-dialog.c
Normal file
203
chooser/gdm-host-chooser-dialog.c
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "gdm-host-chooser-dialog.h"
|
||||||
|
#include "gdm-host-chooser-widget.h"
|
||||||
|
|
||||||
|
struct _GdmHostChooserDialog
|
||||||
|
{
|
||||||
|
GtkDialog parent;
|
||||||
|
|
||||||
|
GtkWidget *chooser_widget;
|
||||||
|
int kind_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_KIND_MASK,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_host_chooser_dialog_class_init (GdmHostChooserDialogClass *klass);
|
||||||
|
static void gdm_host_chooser_dialog_init (GdmHostChooserDialog *host_chooser_dialog);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmHostChooserDialog, gdm_host_chooser_dialog, GTK_TYPE_DIALOG)
|
||||||
|
|
||||||
|
GdmChooserHost *
|
||||||
|
gdm_host_chooser_dialog_get_host (GdmHostChooserDialog *dialog)
|
||||||
|
{
|
||||||
|
GdmChooserHost *host;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_HOST_CHOOSER_DIALOG (dialog), NULL);
|
||||||
|
|
||||||
|
host = gdm_host_chooser_widget_get_host (GDM_HOST_CHOOSER_WIDGET (dialog->chooser_widget));
|
||||||
|
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_host_chooser_dialog_set_kind_mask (GdmHostChooserDialog *dialog,
|
||||||
|
int kind_mask)
|
||||||
|
{
|
||||||
|
if (dialog->kind_mask != kind_mask) {
|
||||||
|
dialog->kind_mask = kind_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_dialog_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmHostChooserDialog *self;
|
||||||
|
|
||||||
|
self = GDM_HOST_CHOOSER_DIALOG (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_KIND_MASK:
|
||||||
|
_gdm_host_chooser_dialog_set_kind_mask (self, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_dialog_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 void
|
||||||
|
on_response (GdmHostChooserDialog *dialog,
|
||||||
|
gint response_id)
|
||||||
|
{
|
||||||
|
switch (response_id) {
|
||||||
|
case GTK_RESPONSE_APPLY:
|
||||||
|
gdm_host_chooser_widget_refresh (GDM_HOST_CHOOSER_WIDGET (dialog->chooser_widget));
|
||||||
|
g_signal_stop_emission_by_name (dialog, "response");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gdm_host_chooser_dialog_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmHostChooserDialog *dialog;
|
||||||
|
|
||||||
|
dialog = GDM_HOST_CHOOSER_DIALOG (G_OBJECT_CLASS (gdm_host_chooser_dialog_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
|
||||||
|
dialog->chooser_widget = gdm_host_chooser_widget_new (dialog->kind_mask);
|
||||||
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), dialog->chooser_widget, TRUE, TRUE, 0);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (dialog->chooser_widget), 5);
|
||||||
|
|
||||||
|
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
|
||||||
|
_("_Refresh"), GTK_RESPONSE_APPLY,
|
||||||
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||||
|
_("C_onnect"), GTK_RESPONSE_OK,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
|
||||||
|
gtk_window_set_title (GTK_WINDOW (dialog), _("Select System"));
|
||||||
|
gtk_window_set_icon_name (GTK_WINDOW (dialog), "computer");
|
||||||
|
|
||||||
|
g_signal_connect (dialog,
|
||||||
|
"response",
|
||||||
|
G_CALLBACK (on_response),
|
||||||
|
dialog);
|
||||||
|
|
||||||
|
gtk_widget_show_all (GTK_WIDGET (dialog));
|
||||||
|
|
||||||
|
return G_OBJECT (dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_dialog_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
g_debug ("Disposing host_chooser_dialog");
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_host_chooser_dialog_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_dialog_class_init (GdmHostChooserDialogClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_host_chooser_dialog_get_property;
|
||||||
|
object_class->set_property = gdm_host_chooser_dialog_set_property;
|
||||||
|
object_class->constructor = gdm_host_chooser_dialog_constructor;
|
||||||
|
object_class->dispose = gdm_host_chooser_dialog_dispose;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_KIND_MASK,
|
||||||
|
g_param_spec_int ("kind-mask",
|
||||||
|
"kind mask",
|
||||||
|
"kind mask",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_dialog_init (GdmHostChooserDialog *dialog)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gdm_host_chooser_dialog_new (int kind_mask)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_HOST_CHOOSER_DIALOG,
|
||||||
|
"kind-mask", kind_mask,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (object);
|
||||||
|
}
|
39
chooser/gdm-host-chooser-dialog.h
Normal file
39
chooser/gdm-host-chooser-dialog.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_HOST_CHOOSER_DIALOG_H
|
||||||
|
#define __GDM_HOST_CHOOSER_DIALOG_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "gdm-chooser-host.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_HOST_CHOOSER_DIALOG (gdm_host_chooser_dialog_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmHostChooserDialog, gdm_host_chooser_dialog, GDM, HOST_CHOOSER_DIALOG, GtkDialog)
|
||||||
|
|
||||||
|
GtkWidget * gdm_host_chooser_dialog_new (int kind_mask);
|
||||||
|
|
||||||
|
GdmChooserHost * gdm_host_chooser_dialog_get_host (GdmHostChooserDialog *dialog);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_HOST_CHOOSER_DIALOG_H */
|
877
chooser/gdm-host-chooser-widget.c
Normal file
877
chooser/gdm-host-chooser-widget.c
Normal file
|
@ -0,0 +1,877 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998, 1999, 2000 Martin K, Petersen <mkp@mkp.net>
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#ifdef HAVE_SYS_SOCKIO_H
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_X11_SUPPORT
|
||||||
|
#include <X11/Xmd.h>
|
||||||
|
#include <X11/Xdmcp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "gdm-address.h"
|
||||||
|
#include "gdm-chooser-host.h"
|
||||||
|
#include "gdm-host-chooser-widget.h"
|
||||||
|
|
||||||
|
struct _GdmHostChooserWidget
|
||||||
|
{
|
||||||
|
GtkBox parent;
|
||||||
|
|
||||||
|
GtkWidget *treeview;
|
||||||
|
|
||||||
|
int kind_mask;
|
||||||
|
|
||||||
|
char **hosts;
|
||||||
|
|
||||||
|
XdmcpBuffer broadcast_buf;
|
||||||
|
XdmcpBuffer query_buf;
|
||||||
|
gboolean have_ipv6;
|
||||||
|
int socket_fd;
|
||||||
|
guint io_watch_id;
|
||||||
|
guint scan_time_id;
|
||||||
|
guint ping_try_id;
|
||||||
|
|
||||||
|
int ping_tries;
|
||||||
|
|
||||||
|
GSList *broadcast_addresses;
|
||||||
|
GSList *query_addresses;
|
||||||
|
GSList *chooser_hosts;
|
||||||
|
|
||||||
|
GdmChooserHost *current_host;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_KIND_MASK,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HOST_ACTIVATED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
static void gdm_host_chooser_widget_class_init (GdmHostChooserWidgetClass *klass);
|
||||||
|
static void gdm_host_chooser_widget_init (GdmHostChooserWidget *host_chooser_widget);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmHostChooserWidget, gdm_host_chooser_widget, GTK_TYPE_BOX)
|
||||||
|
|
||||||
|
#define GDM_XDMCP_PROTOCOL_VERSION 1001
|
||||||
|
#define SCAN_TIMEOUT 30
|
||||||
|
#define PING_TIMEOUT 2
|
||||||
|
#define PING_TRIES 3
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CHOOSER_LIST_ICON_COLUMN = 0,
|
||||||
|
CHOOSER_LIST_LABEL_COLUMN,
|
||||||
|
CHOOSER_LIST_HOST_COLUMN
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
chooser_host_add (GdmHostChooserWidget *widget,
|
||||||
|
GdmChooserHost *host)
|
||||||
|
{
|
||||||
|
widget->chooser_hosts = g_slist_prepend (widget->chooser_hosts, host);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void
|
||||||
|
chooser_host_remove (GdmHostChooserWidget *widget,
|
||||||
|
GdmChooserHost *host)
|
||||||
|
{
|
||||||
|
widget->chooser_hosts = g_slist_remove (widget->chooser_hosts, host);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
address_hostnames_equal (GdmAddress *address,
|
||||||
|
GdmAddress *other_address)
|
||||||
|
{
|
||||||
|
char *hostname, *other_hostname;
|
||||||
|
gboolean are_equal;
|
||||||
|
|
||||||
|
if (gdm_address_equal (address, other_address)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gdm_address_get_hostname (address, &hostname)) {
|
||||||
|
gdm_address_get_numeric_info (address, &hostname, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gdm_address_get_hostname (other_address, &other_hostname)) {
|
||||||
|
gdm_address_get_numeric_info (other_address, &other_hostname, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
are_equal = g_strcmp0 (hostname, other_hostname) == 0;
|
||||||
|
|
||||||
|
g_free (hostname);
|
||||||
|
g_free (other_hostname);
|
||||||
|
|
||||||
|
return are_equal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdmChooserHost *
|
||||||
|
find_known_host (GdmHostChooserWidget *widget,
|
||||||
|
GdmAddress *address)
|
||||||
|
{
|
||||||
|
GSList *li;
|
||||||
|
GdmChooserHost *host;
|
||||||
|
|
||||||
|
for (li = widget->chooser_hosts; li != NULL; li = li->next) {
|
||||||
|
GdmAddress *other_address;
|
||||||
|
|
||||||
|
host = li->data;
|
||||||
|
|
||||||
|
other_address = gdm_chooser_host_get_address (host);
|
||||||
|
|
||||||
|
if (address_hostnames_equal (address, other_address)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
host = NULL;
|
||||||
|
out:
|
||||||
|
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
browser_add_host (GdmHostChooserWidget *widget,
|
||||||
|
GdmChooserHost *host)
|
||||||
|
{
|
||||||
|
char *hostname;
|
||||||
|
char *name;
|
||||||
|
char *desc;
|
||||||
|
char *label;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
GtkTreeSelection *selection;
|
||||||
|
|
||||||
|
g_assert (host != NULL);
|
||||||
|
|
||||||
|
if (! gdm_chooser_host_get_willing (host)) {
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (widget), TRUE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = gdm_address_get_hostname (gdm_chooser_host_get_address (host), &hostname);
|
||||||
|
if (! res) {
|
||||||
|
gdm_address_get_numeric_info (gdm_chooser_host_get_address (host), &hostname, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
name = g_markup_escape_text (hostname, -1);
|
||||||
|
desc = g_markup_escape_text (gdm_chooser_host_get_description (host), -1);
|
||||||
|
label = g_strdup_printf ("<b>%s</b>\n%s", name, desc);
|
||||||
|
g_free (name);
|
||||||
|
g_free (desc);
|
||||||
|
|
||||||
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget->treeview));
|
||||||
|
|
||||||
|
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
|
||||||
|
gtk_list_store_set (GTK_LIST_STORE (model),
|
||||||
|
&iter,
|
||||||
|
CHOOSER_LIST_ICON_COLUMN, NULL,
|
||||||
|
CHOOSER_LIST_LABEL_COLUMN, label,
|
||||||
|
CHOOSER_LIST_HOST_COLUMN, host,
|
||||||
|
-1);
|
||||||
|
g_free (label);
|
||||||
|
|
||||||
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->treeview));
|
||||||
|
if (!gtk_tree_selection_get_selected (selection, NULL, NULL)) {
|
||||||
|
gtk_tree_selection_select_iter (selection, &iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
decode_packet (GIOChannel *source,
|
||||||
|
GIOCondition condition,
|
||||||
|
GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage clnt_ss;
|
||||||
|
GdmAddress *address;
|
||||||
|
int ss_len;
|
||||||
|
XdmcpHeader header;
|
||||||
|
int res;
|
||||||
|
static XdmcpBuffer buf;
|
||||||
|
ARRAY8 auth = {0};
|
||||||
|
ARRAY8 host = {0};
|
||||||
|
ARRAY8 stat = {0};
|
||||||
|
char *status;
|
||||||
|
GdmChooserHost *chooser_host;
|
||||||
|
|
||||||
|
status = NULL;
|
||||||
|
address = NULL;
|
||||||
|
|
||||||
|
g_debug ("decode_packet: GIOCondition %d", (int)condition);
|
||||||
|
|
||||||
|
if ( ! (condition & G_IO_IN)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss_len = (int) sizeof (clnt_ss);
|
||||||
|
|
||||||
|
res = XdmcpFill (widget->socket_fd, &buf, (XdmcpNetaddr)&clnt_ss, &ss_len);
|
||||||
|
if G_UNLIKELY (! res) {
|
||||||
|
g_debug (_("XDMCP: Could not create XDMCP buffer!"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = XdmcpReadHeader (&buf, &header);
|
||||||
|
if G_UNLIKELY (! res) {
|
||||||
|
g_warning (_("XDMCP: Could not read XDMCP header!"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if G_UNLIKELY (header.version != XDM_PROTOCOL_VERSION &&
|
||||||
|
header.version != GDM_XDMCP_PROTOCOL_VERSION) {
|
||||||
|
g_warning (_("XDMCP: Incorrect XDMCP version!"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
address = gdm_address_new_from_sockaddr ((struct sockaddr *) &clnt_ss, ss_len);
|
||||||
|
if (address == NULL) {
|
||||||
|
g_warning (_("XDMCP: Unable to parse address"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdm_address_debug (address);
|
||||||
|
|
||||||
|
if (header.opcode == WILLING) {
|
||||||
|
if (! XdmcpReadARRAY8 (&buf, &auth)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! XdmcpReadARRAY8 (&buf, &host)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! XdmcpReadARRAY8 (&buf, &stat)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = g_strndup ((char *) stat.data, MIN (stat.length, 256));
|
||||||
|
} else if (header.opcode == UNWILLING) {
|
||||||
|
/* immaterial, will not be shown */
|
||||||
|
status = NULL;
|
||||||
|
} else {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("STATUS: %s", status);
|
||||||
|
|
||||||
|
chooser_host = find_known_host (widget, address);
|
||||||
|
if (chooser_host == NULL) {
|
||||||
|
chooser_host = g_object_new (GDM_TYPE_CHOOSER_HOST,
|
||||||
|
"address", address,
|
||||||
|
"description", status,
|
||||||
|
"willing", (header.opcode == WILLING),
|
||||||
|
"kind", GDM_CHOOSER_HOST_KIND_XDMCP,
|
||||||
|
NULL);
|
||||||
|
chooser_host_add (widget, chooser_host);
|
||||||
|
browser_add_host (widget, chooser_host);
|
||||||
|
} else {
|
||||||
|
/* server changed it's mind */
|
||||||
|
if (header.opcode == WILLING
|
||||||
|
&& ! gdm_chooser_host_get_willing (chooser_host)) {
|
||||||
|
browser_add_host (widget, chooser_host);
|
||||||
|
g_object_set (chooser_host, "willing", TRUE, NULL);
|
||||||
|
}
|
||||||
|
/* FIXME: handle unwilling? */
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (header.opcode == WILLING) {
|
||||||
|
XdmcpDisposeARRAY8 (&auth);
|
||||||
|
XdmcpDisposeARRAY8 (&host);
|
||||||
|
XdmcpDisposeARRAY8 (&stat);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (status);
|
||||||
|
gdm_address_free (address);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_ping (GdmHostChooserWidget *widget,
|
||||||
|
gboolean full)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
g_debug ("do ping full:%d", full);
|
||||||
|
|
||||||
|
for (l = widget->broadcast_addresses; l != NULL; l = l->next) {
|
||||||
|
GdmAddress *address;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
address = l->data;
|
||||||
|
|
||||||
|
gdm_address_debug (address);
|
||||||
|
errno = 0;
|
||||||
|
g_debug ("fd:%d", widget->socket_fd);
|
||||||
|
res = XdmcpFlush (widget->socket_fd,
|
||||||
|
&widget->broadcast_buf,
|
||||||
|
(XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
|
||||||
|
(int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
|
||||||
|
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to flush the XDMCP broadcast packet: %s", g_strerror (errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (full) {
|
||||||
|
for (l = widget->query_addresses; l != NULL; l = l->next) {
|
||||||
|
GdmAddress *address;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
address = l->data;
|
||||||
|
|
||||||
|
gdm_address_debug (address);
|
||||||
|
res = XdmcpFlush (widget->socket_fd,
|
||||||
|
&widget->query_buf,
|
||||||
|
(XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
|
||||||
|
(int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to flush the XDMCP query packet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
ping_try (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
do_ping (widget, FALSE);
|
||||||
|
|
||||||
|
widget->ping_tries --;
|
||||||
|
|
||||||
|
if (widget->ping_tries <= 0) {
|
||||||
|
widget->ping_try_id = 0;
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdmcp_discover (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (manage), FALSE);
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (rescan), FALSE);
|
||||||
|
gtk_list_store_clear (GTK_LIST_STORE (browser_model));
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (browser), FALSE);
|
||||||
|
gtk_label_set_label (GTK_LABEL (status_label),
|
||||||
|
_(scanning_message));
|
||||||
|
|
||||||
|
while (hl) {
|
||||||
|
gdm_chooser_host_dispose ((GdmChooserHost *) hl->data);
|
||||||
|
hl = hl->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (chooser_hosts);
|
||||||
|
chooser_hosts = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do_ping (widget, TRUE);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_clear_handle_id (&widget->scan_time_id, g_source_remove);
|
||||||
|
|
||||||
|
widget->scan_time_id = g_timeout_add_seconds (SCAN_TIMEOUT,
|
||||||
|
chooser_scan_time_update,
|
||||||
|
widget);
|
||||||
|
#endif
|
||||||
|
/* Note we already used up one try */
|
||||||
|
widget->ping_tries = PING_TRIES - 1;
|
||||||
|
g_clear_handle_id (&widget->ping_try_id, g_source_remove);
|
||||||
|
|
||||||
|
widget->ping_try_id = g_timeout_add_seconds (PING_TIMEOUT,
|
||||||
|
(GSourceFunc)ping_try,
|
||||||
|
widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find broadcast address for all active, non pointopoint interfaces */
|
||||||
|
static void
|
||||||
|
find_broadcast_addresses (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int num;
|
||||||
|
int sock;
|
||||||
|
struct ifconf ifc;
|
||||||
|
char *buf;
|
||||||
|
struct ifreq *ifr;
|
||||||
|
|
||||||
|
g_debug ("Finding broadcast addresses");
|
||||||
|
|
||||||
|
sock = socket (AF_INET, SOCK_DGRAM, 0);
|
||||||
|
#ifdef SIOCGIFNUM
|
||||||
|
if (ioctl (sock, SIOCGIFNUM, &num) < 0) {
|
||||||
|
num = 64;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
num = 64;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ifc.ifc_len = sizeof (struct ifreq) * num;
|
||||||
|
ifc.ifc_buf = buf = g_malloc0 (ifc.ifc_len);
|
||||||
|
if (ioctl (sock, SIOCGIFCONF, &ifc) < 0) {
|
||||||
|
g_warning ("Could not get local addresses!");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifr = ifc.ifc_req;
|
||||||
|
num = ifc.ifc_len / sizeof (struct ifreq);
|
||||||
|
for (i = 0 ; i < num ; i++) {
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
name = ifr[i].ifr_name;
|
||||||
|
g_debug ("Checking if %s", name);
|
||||||
|
if (name != NULL && name[0] != '\0') {
|
||||||
|
struct ifreq ifreq;
|
||||||
|
GdmAddress *address;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
|
memset (&ifreq, 0, sizeof (ifreq));
|
||||||
|
|
||||||
|
strncpy (ifreq.ifr_name,
|
||||||
|
ifr[i].ifr_name,
|
||||||
|
sizeof (ifreq.ifr_name));
|
||||||
|
/* paranoia */
|
||||||
|
ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0';
|
||||||
|
|
||||||
|
if ((ioctl (sock, SIOCGIFFLAGS, &ifreq) < 0) && (errno != ENXIO)) {
|
||||||
|
g_warning ("Could not get SIOCGIFFLAGS for %s", ifr[i].ifr_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ifreq.ifr_flags & IFF_UP) == 0 ||
|
||||||
|
(ifreq.ifr_flags & IFF_BROADCAST) == 0 ||
|
||||||
|
ioctl (sock, SIOCGIFBRDADDR, &ifreq) < 0) {
|
||||||
|
g_debug ("Skipping if %s", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (&sin, &ifreq.ifr_broadaddr, sizeof (struct sockaddr_in));
|
||||||
|
sin.sin_port = htons (XDM_UDP_PORT);
|
||||||
|
address = gdm_address_new_from_sockaddr ((struct sockaddr *) &sin, sizeof (sin));
|
||||||
|
if (address != NULL) {
|
||||||
|
g_debug ("Adding if %s", name);
|
||||||
|
gdm_address_debug (address);
|
||||||
|
|
||||||
|
widget->broadcast_addresses = g_slist_append (widget->broadcast_addresses, address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
g_free (buf);
|
||||||
|
close (sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_hosts (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; widget->hosts != NULL && widget->hosts[i] != NULL; i++) {
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *result;
|
||||||
|
struct addrinfo *ai;
|
||||||
|
int gaierr;
|
||||||
|
const char *name;
|
||||||
|
char serv_buf [NI_MAXSERV];
|
||||||
|
const char *serv;
|
||||||
|
|
||||||
|
name = widget->hosts[i];
|
||||||
|
|
||||||
|
if (strcmp (name, "BROADCAST") == 0) {
|
||||||
|
find_broadcast_addresses (widget);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (name, "MULTICAST") == 0) {
|
||||||
|
/*gdm_chooser_find_mcaddr ();*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = NULL;
|
||||||
|
memset (&hints, 0, sizeof (hints));
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
snprintf (serv_buf, sizeof (serv_buf), "%u", XDM_UDP_PORT);
|
||||||
|
serv = serv_buf;
|
||||||
|
|
||||||
|
gaierr = getaddrinfo (name, serv, &hints, &result);
|
||||||
|
if (gaierr != 0) {
|
||||||
|
g_warning ("Unable to get address info for name %s: %s", name, gai_strerror (gaierr));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ai = result; ai != NULL; ai = ai->ai_next) {
|
||||||
|
GdmAddress *address;
|
||||||
|
|
||||||
|
address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
|
||||||
|
if (address != NULL) {
|
||||||
|
widget->query_addresses = g_slist_append (widget->query_addresses, address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget->broadcast_addresses == NULL && widget->query_addresses == NULL) {
|
||||||
|
find_broadcast_addresses (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdmcp_init (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
XdmcpHeader header;
|
||||||
|
int sockopts;
|
||||||
|
int res;
|
||||||
|
GIOChannel *ioc;
|
||||||
|
ARRAYofARRAY8 aanames;
|
||||||
|
|
||||||
|
sockopts = 1;
|
||||||
|
|
||||||
|
widget->socket_fd = -1;
|
||||||
|
|
||||||
|
/* Open socket for communication */
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
widget->socket_fd = socket (AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if (widget->socket_fd != -1) {
|
||||||
|
widget->have_ipv6 = TRUE;
|
||||||
|
#ifdef IPV6_V6ONLY
|
||||||
|
{
|
||||||
|
int zero = 0;
|
||||||
|
if (setsockopt(widget->socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) < 0)
|
||||||
|
g_warning("setsockopt(IPV6_V6ONLY): %s", g_strerror(errno));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (! widget->have_ipv6) {
|
||||||
|
widget->socket_fd = socket (AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (widget->socket_fd == -1) {
|
||||||
|
g_critical ("Could not create socket!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = setsockopt (widget->socket_fd,
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_BROADCAST,
|
||||||
|
(char *) &sockopts,
|
||||||
|
sizeof (sockopts));
|
||||||
|
if (res < 0) {
|
||||||
|
g_critical ("Could not set socket options!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assemble XDMCP BROADCAST_QUERY packet in static buffer */
|
||||||
|
memset (&header, 0, sizeof (XdmcpHeader));
|
||||||
|
header.opcode = (CARD16) BROADCAST_QUERY;
|
||||||
|
header.length = 1;
|
||||||
|
header.version = XDM_PROTOCOL_VERSION;
|
||||||
|
aanames.length = 0;
|
||||||
|
XdmcpWriteHeader (&widget->broadcast_buf, &header);
|
||||||
|
XdmcpWriteARRAYofARRAY8 (&widget->broadcast_buf, &aanames);
|
||||||
|
|
||||||
|
/* Assemble XDMCP QUERY packet in static buffer */
|
||||||
|
memset (&header, 0, sizeof (XdmcpHeader));
|
||||||
|
header.opcode = (CARD16) QUERY;
|
||||||
|
header.length = 1;
|
||||||
|
header.version = XDM_PROTOCOL_VERSION;
|
||||||
|
memset (&widget->query_buf, 0, sizeof (XdmcpBuffer));
|
||||||
|
XdmcpWriteHeader (&widget->query_buf, &header);
|
||||||
|
XdmcpWriteARRAYofARRAY8 (&widget->query_buf, &aanames);
|
||||||
|
|
||||||
|
add_hosts (widget);
|
||||||
|
|
||||||
|
ioc = g_io_channel_unix_new (widget->socket_fd);
|
||||||
|
g_io_channel_set_encoding (ioc, NULL, NULL);
|
||||||
|
g_io_channel_set_buffered (ioc, FALSE);
|
||||||
|
widget->io_watch_id = g_io_add_watch (ioc,
|
||||||
|
G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
|
||||||
|
(GIOFunc)decode_packet,
|
||||||
|
widget);
|
||||||
|
g_io_channel_unref (ioc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_host_chooser_widget_refresh (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_HOST_CHOOSER_WIDGET (widget));
|
||||||
|
|
||||||
|
xdmcp_discover (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmChooserHost *
|
||||||
|
gdm_host_chooser_widget_get_host (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GdmChooserHost *host;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_HOST_CHOOSER_WIDGET (widget), NULL);
|
||||||
|
|
||||||
|
host = NULL;
|
||||||
|
if (widget->current_host != NULL) {
|
||||||
|
host = g_object_ref (widget->current_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_host_chooser_widget_set_kind_mask (GdmHostChooserWidget *widget,
|
||||||
|
int kind_mask)
|
||||||
|
{
|
||||||
|
if (widget->kind_mask != kind_mask) {
|
||||||
|
widget->kind_mask = kind_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_widget_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmHostChooserWidget *self;
|
||||||
|
|
||||||
|
self = GDM_HOST_CHOOSER_WIDGET (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_KIND_MASK:
|
||||||
|
_gdm_host_chooser_widget_set_kind_mask (self, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_widget_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 *
|
||||||
|
gdm_host_chooser_widget_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmHostChooserWidget *widget;
|
||||||
|
|
||||||
|
widget = GDM_HOST_CHOOSER_WIDGET (G_OBJECT_CLASS (gdm_host_chooser_widget_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
xdmcp_init (widget);
|
||||||
|
xdmcp_discover (widget);
|
||||||
|
|
||||||
|
return G_OBJECT (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_widget_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
GdmHostChooserWidget *widget;
|
||||||
|
|
||||||
|
widget = GDM_HOST_CHOOSER_WIDGET (object);
|
||||||
|
|
||||||
|
g_debug ("Disposing host_chooser_widget");
|
||||||
|
|
||||||
|
if (widget->broadcast_addresses != NULL) {
|
||||||
|
g_slist_foreach (widget->broadcast_addresses,
|
||||||
|
(GFunc)gdm_address_free,
|
||||||
|
NULL);
|
||||||
|
g_slist_free (widget->broadcast_addresses);
|
||||||
|
widget->broadcast_addresses = NULL;
|
||||||
|
}
|
||||||
|
if (widget->query_addresses != NULL) {
|
||||||
|
g_slist_foreach (widget->query_addresses,
|
||||||
|
(GFunc)gdm_address_free,
|
||||||
|
NULL);
|
||||||
|
g_slist_free (widget->query_addresses);
|
||||||
|
widget->query_addresses = NULL;
|
||||||
|
}
|
||||||
|
if (widget->chooser_hosts != NULL) {
|
||||||
|
g_slist_foreach (widget->chooser_hosts,
|
||||||
|
(GFunc)g_object_unref,
|
||||||
|
NULL);
|
||||||
|
g_slist_free (widget->chooser_hosts);
|
||||||
|
widget->chooser_hosts = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget->current_host = NULL;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_host_chooser_widget_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_widget_class_init (GdmHostChooserWidgetClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_host_chooser_widget_get_property;
|
||||||
|
object_class->set_property = gdm_host_chooser_widget_set_property;
|
||||||
|
object_class->constructor = gdm_host_chooser_widget_constructor;
|
||||||
|
object_class->dispose = gdm_host_chooser_widget_dispose;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_KIND_MASK,
|
||||||
|
g_param_spec_int ("kind-mask",
|
||||||
|
"kind mask",
|
||||||
|
"kind mask",
|
||||||
|
0,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
signals [HOST_ACTIVATED] = g_signal_new ("host-activated",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_host_selected (GtkTreeSelection *selection,
|
||||||
|
GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GtkTreeModel *model = NULL;
|
||||||
|
GtkTreeIter iter = {0};
|
||||||
|
GdmChooserHost *curhost;
|
||||||
|
|
||||||
|
curhost = NULL;
|
||||||
|
|
||||||
|
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
|
||||||
|
gtk_tree_model_get (model, &iter, CHOOSER_LIST_HOST_COLUMN, &curhost, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
widget->current_host = curhost;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_row_activated (GtkTreeView *tree_view,
|
||||||
|
GtkTreePath *tree_path,
|
||||||
|
GtkTreeViewColumn *tree_column,
|
||||||
|
GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
g_signal_emit (widget, signals[HOST_ACTIVATED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_host_chooser_widget_init (GdmHostChooserWidget *widget)
|
||||||
|
{
|
||||||
|
GtkWidget *scrolled;
|
||||||
|
GtkTreeSelection *selection;
|
||||||
|
GtkTreeViewColumn *column;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
|
||||||
|
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||||
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
|
||||||
|
GTK_SHADOW_IN);
|
||||||
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
|
||||||
|
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
||||||
|
gtk_box_pack_start (GTK_BOX (widget), scrolled, TRUE, TRUE, 0);
|
||||||
|
|
||||||
|
widget->treeview = gtk_tree_view_new ();
|
||||||
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget->treeview), FALSE);
|
||||||
|
g_signal_connect (widget->treeview,
|
||||||
|
"row-activated",
|
||||||
|
G_CALLBACK (on_row_activated),
|
||||||
|
widget);
|
||||||
|
gtk_container_add (GTK_CONTAINER (scrolled), widget->treeview);
|
||||||
|
|
||||||
|
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->treeview));
|
||||||
|
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
|
||||||
|
g_signal_connect (selection, "changed",
|
||||||
|
G_CALLBACK (on_host_selected),
|
||||||
|
widget);
|
||||||
|
|
||||||
|
model = (GtkTreeModel *)gtk_list_store_new (3,
|
||||||
|
GDK_TYPE_PIXBUF,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_POINTER);
|
||||||
|
gtk_tree_view_set_model (GTK_TREE_VIEW (widget->treeview), model);
|
||||||
|
|
||||||
|
column = gtk_tree_view_column_new_with_attributes ("Icon",
|
||||||
|
gtk_cell_renderer_pixbuf_new (),
|
||||||
|
"pixbuf", CHOOSER_LIST_ICON_COLUMN,
|
||||||
|
NULL);
|
||||||
|
gtk_tree_view_append_column (GTK_TREE_VIEW (widget->treeview), column);
|
||||||
|
|
||||||
|
column = gtk_tree_view_column_new_with_attributes ("Hostname",
|
||||||
|
gtk_cell_renderer_text_new (),
|
||||||
|
"markup", CHOOSER_LIST_LABEL_COLUMN,
|
||||||
|
NULL);
|
||||||
|
gtk_tree_view_append_column (GTK_TREE_VIEW (widget->treeview), column);
|
||||||
|
|
||||||
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
|
||||||
|
CHOOSER_LIST_LABEL_COLUMN,
|
||||||
|
GTK_SORT_ASCENDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *
|
||||||
|
gdm_host_chooser_widget_new (int kind_mask)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_HOST_CHOOSER_WIDGET,
|
||||||
|
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||||
|
"kind-mask", kind_mask,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (object);
|
||||||
|
}
|
41
chooser/gdm-host-chooser-widget.h
Normal file
41
chooser/gdm-host-chooser-widget.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_HOST_CHOOSER_WIDGET_H
|
||||||
|
#define __GDM_HOST_CHOOSER_WIDGET_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "gdm-chooser-host.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_HOST_CHOOSER_WIDGET (gdm_host_chooser_widget_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmHostChooserWidget, gdm_host_chooser_widget, GDM, HOST_CHOOSER_WIDGET, GtkBox)
|
||||||
|
|
||||||
|
GtkWidget * gdm_host_chooser_widget_new (int kind_mask);
|
||||||
|
|
||||||
|
void gdm_host_chooser_widget_refresh (GdmHostChooserWidget *widget);
|
||||||
|
|
||||||
|
GdmChooserHost * gdm_host_chooser_widget_get_host (GdmHostChooserWidget *widget);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_HOST_CHOOSER_WIDGET_H */
|
252
chooser/gdm-host-chooser.c
Normal file
252
chooser/gdm-host-chooser.c
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
#include "gdm-log.h"
|
||||||
|
|
||||||
|
#include "gdm-chooser-host.h"
|
||||||
|
#include "gdm-host-chooser-dialog.h"
|
||||||
|
|
||||||
|
#define ACCESSIBILITY_KEY "/desktop/gnome/interface/accessibility"
|
||||||
|
|
||||||
|
static Atom AT_SPI_IOR;
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
assistive_registry_launch (void)
|
||||||
|
{
|
||||||
|
GPid pid;
|
||||||
|
GError *error;
|
||||||
|
const char *command;
|
||||||
|
char **argv;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
command = AT_SPI_REGISTRYD_DIR "/at-spi-registryd";
|
||||||
|
|
||||||
|
argv = NULL;
|
||||||
|
error = NULL;
|
||||||
|
res = g_shell_parse_argv (command, NULL, &argv, &error);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to parse command: %s", error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
res = g_spawn_async (NULL,
|
||||||
|
argv,
|
||||||
|
NULL,
|
||||||
|
G_SPAWN_SEARCH_PATH
|
||||||
|
| G_SPAWN_STDOUT_TO_DEV_NULL
|
||||||
|
| G_SPAWN_STDERR_TO_DEV_NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&pid,
|
||||||
|
&error);
|
||||||
|
g_strfreev (argv);
|
||||||
|
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to run command %s: %s", command, error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kill (pid, 0) < 0) {
|
||||||
|
g_warning ("at-spi-registryd not running");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkFilterReturn
|
||||||
|
filter_watch (GdkXEvent *xevent,
|
||||||
|
GdkEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
XEvent *xev = (XEvent *)xevent;
|
||||||
|
|
||||||
|
if (xev->xany.type == PropertyNotify
|
||||||
|
&& xev->xproperty.atom == AT_SPI_IOR) {
|
||||||
|
gtk_main_quit ();
|
||||||
|
|
||||||
|
return GDK_FILTER_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDK_FILTER_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
filter_timeout (gpointer data)
|
||||||
|
{
|
||||||
|
g_warning ("The accessibility registry was not found.");
|
||||||
|
|
||||||
|
gtk_main_quit ();
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assistive_registry_start (void)
|
||||||
|
{
|
||||||
|
GdkWindow *root;
|
||||||
|
guint tid;
|
||||||
|
|
||||||
|
root = gdk_get_default_root_window ();
|
||||||
|
|
||||||
|
if ( ! AT_SPI_IOR) {
|
||||||
|
AT_SPI_IOR = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "AT_SPI_IOR", False);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_window_set_events (root, GDK_PROPERTY_CHANGE_MASK);
|
||||||
|
|
||||||
|
if ( ! assistive_registry_launch ()) {
|
||||||
|
g_warning ("The accessibility registry could not be started.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdk_window_add_filter (root, filter_watch, NULL);
|
||||||
|
tid = g_timeout_add_seconds (5, filter_timeout, NULL);
|
||||||
|
|
||||||
|
gtk_main ();
|
||||||
|
|
||||||
|
gdk_window_remove_filter (root, filter_watch, NULL);
|
||||||
|
g_source_remove (tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
at_set_gtk_modules (void)
|
||||||
|
{
|
||||||
|
GSList *modules_list;
|
||||||
|
GSList *l;
|
||||||
|
const char *old;
|
||||||
|
char **modules;
|
||||||
|
gboolean found_gail;
|
||||||
|
gboolean found_atk_bridge;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
modules_list = NULL;
|
||||||
|
found_gail = FALSE;
|
||||||
|
found_atk_bridge = FALSE;
|
||||||
|
|
||||||
|
if ((old = g_getenv ("GTK_MODULES")) != NULL) {
|
||||||
|
modules = g_strsplit (old, ":", -1);
|
||||||
|
for (n = 0; modules[n]; n++) {
|
||||||
|
if (!strcmp (modules[n], "gail")) {
|
||||||
|
found_gail = TRUE;
|
||||||
|
} else if (!strcmp (modules[n], "atk-bridge")) {
|
||||||
|
found_atk_bridge = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
modules_list = g_slist_prepend (modules_list, modules[n]);
|
||||||
|
modules[n] = NULL;
|
||||||
|
}
|
||||||
|
g_free (modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_gail) {
|
||||||
|
modules_list = g_slist_prepend (modules_list, "gail");
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_atk_bridge) {
|
||||||
|
modules_list = g_slist_prepend (modules_list, "atk-bridge");
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
|
||||||
|
modules = g_new (char *, n + 1);
|
||||||
|
modules[n--] = NULL;
|
||||||
|
for (l = modules_list; l; l = l->next) {
|
||||||
|
modules[n--] = g_strdup (l->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_setenv ("GTK_MODULES", g_strjoinv (":", modules), TRUE);
|
||||||
|
g_strfreev (modules);
|
||||||
|
g_slist_free (modules_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_a11y (void)
|
||||||
|
{
|
||||||
|
assistive_registry_start ();
|
||||||
|
at_set_gtk_modules ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
GtkWidget *chooser;
|
||||||
|
|
||||||
|
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||||
|
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||||
|
textdomain (GETTEXT_PACKAGE);
|
||||||
|
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
|
gdm_log_init ();
|
||||||
|
gdm_log_set_debug (TRUE);
|
||||||
|
|
||||||
|
g_debug ("Chooser for display %s xauthority:%s",
|
||||||
|
g_getenv ("DISPLAY"),
|
||||||
|
g_getenv ("XAUTHORITY"));
|
||||||
|
|
||||||
|
gdk_init (&argc, &argv);
|
||||||
|
|
||||||
|
load_a11y ();
|
||||||
|
|
||||||
|
gtk_init (&argc, &argv);
|
||||||
|
|
||||||
|
chooser = gdm_host_chooser_dialog_new (GDM_CHOOSER_HOST_KIND_MASK_ALL);
|
||||||
|
gtk_widget_set_size_request (chooser, 480, 600);
|
||||||
|
|
||||||
|
if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK) {
|
||||||
|
GdmChooserHost *host;
|
||||||
|
|
||||||
|
host = gdm_host_chooser_dialog_get_host (GDM_HOST_CHOOSER_DIALOG (chooser));
|
||||||
|
if (host != NULL) {
|
||||||
|
char *hostname;
|
||||||
|
/* FIXME: handle different host types here? */
|
||||||
|
|
||||||
|
hostname = NULL;
|
||||||
|
gdm_address_get_hostname (gdm_chooser_host_get_address (host), &hostname);
|
||||||
|
/* FIXME: fall back to numerical address? */
|
||||||
|
if (hostname != NULL) {
|
||||||
|
g_print ("hostname: %s\n", hostname);
|
||||||
|
g_free (hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_destroy (chooser);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
50
chooser/meson.build
Normal file
50
chooser/meson.build
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Simple chooser
|
||||||
|
gdm_simple_chooser_src = [
|
||||||
|
'chooser-main.c',
|
||||||
|
'gdm-chooser-host.c',
|
||||||
|
'gdm-chooser-session.c',
|
||||||
|
'gdm-host-chooser-dialog.c',
|
||||||
|
'gdm-host-chooser-widget.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
gdm_simple_chooser_deps = [
|
||||||
|
glib_dep,
|
||||||
|
gtk_dep,
|
||||||
|
libgdmcommon_dep,
|
||||||
|
libgdm_dep,
|
||||||
|
x_deps,
|
||||||
|
xdmcp_dep,
|
||||||
|
]
|
||||||
|
|
||||||
|
gdm_simple_chooser = executable('gdm-simple-chooser',
|
||||||
|
gdm_simple_chooser_src,
|
||||||
|
dependencies: gdm_simple_chooser_deps,
|
||||||
|
include_directories: config_h_dir,
|
||||||
|
install: true,
|
||||||
|
install_dir: get_option('libexecdir'),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Host chooser
|
||||||
|
gdm_host_chooser_src = [
|
||||||
|
'gdm-host-chooser.c',
|
||||||
|
'gdm-chooser-host.c',
|
||||||
|
'gdm-host-chooser-dialog.c',
|
||||||
|
'gdm-host-chooser-widget.c',
|
||||||
|
]
|
||||||
|
|
||||||
|
gdm_host_chooser_deps = [
|
||||||
|
glib_dep,
|
||||||
|
gtk_dep,
|
||||||
|
libgdmcommon_dep,
|
||||||
|
libgdm_dep,
|
||||||
|
x_deps,
|
||||||
|
xdmcp_dep,
|
||||||
|
]
|
||||||
|
|
||||||
|
gdm_host_chooser = executable('gdm-host-chooser',
|
||||||
|
gdm_host_chooser_src,
|
||||||
|
dependencies: gdm_host_chooser_deps,
|
||||||
|
include_directories: config_h_dir,
|
||||||
|
install: true,
|
||||||
|
install_dir: get_option('libexecdir'),
|
||||||
|
)
|
3
common/gdb-cmd
Normal file
3
common/gdb-cmd
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
bt
|
||||||
|
thread apply all bt full
|
||||||
|
q
|
543
common/gdm-address.c
Normal file
543
common/gdm-address.c
Normal file
|
@ -0,0 +1,543 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#ifdef HAVE_STROPTS_H
|
||||||
|
#include <stropts.h>
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKIO_H
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
#endif
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#else
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-address.h"
|
||||||
|
|
||||||
|
struct _GdmAddress
|
||||||
|
{
|
||||||
|
struct sockaddr_storage *ss;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Register GdmAddress in the glib type system */
|
||||||
|
GType
|
||||||
|
gdm_address_get_type (void)
|
||||||
|
{
|
||||||
|
static GType addr_type = 0;
|
||||||
|
|
||||||
|
if (addr_type == 0) {
|
||||||
|
addr_type = g_boxed_type_register_static ("GdmAddress",
|
||||||
|
(GBoxedCopyFunc) gdm_address_copy,
|
||||||
|
(GBoxedFreeFunc) gdm_address_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdm_address_get_family_type:
|
||||||
|
* @address: A pointer to a #GdmAddress
|
||||||
|
*
|
||||||
|
* Use this function to retrive the address family of @address.
|
||||||
|
*
|
||||||
|
* Return value: The address family of @address.
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
gdm_address_get_family_type (GdmAddress *address)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (address != NULL, -1);
|
||||||
|
|
||||||
|
return address->ss->ss_family;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdm_address_new_from_sockaddr:
|
||||||
|
* @sa: A pointer to a sockaddr.
|
||||||
|
* @size: size of sockaddr in bytes.
|
||||||
|
*
|
||||||
|
* Creates a new #GdmAddress from @sa.
|
||||||
|
*
|
||||||
|
* Return value: The new #GdmAddress
|
||||||
|
* or %NULL if @sa was invalid or the address family isn't supported.
|
||||||
|
**/
|
||||||
|
GdmAddress *
|
||||||
|
gdm_address_new_from_sockaddr (struct sockaddr *sa,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
GdmAddress *addr;
|
||||||
|
|
||||||
|
g_return_val_if_fail (sa != NULL, NULL);
|
||||||
|
g_return_val_if_fail (size >= sizeof (struct sockaddr), NULL);
|
||||||
|
g_return_val_if_fail (size <= sizeof (struct sockaddr_storage), NULL);
|
||||||
|
|
||||||
|
addr = g_new0 (GdmAddress, 1);
|
||||||
|
addr->ss = g_new0 (struct sockaddr_storage, 1);
|
||||||
|
memcpy (addr->ss, sa, size);
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdm_address_get_sockaddr_storage:
|
||||||
|
* @address: A #GdmAddress
|
||||||
|
*
|
||||||
|
* This function tanslates @address into a equivalent
|
||||||
|
* sockaddr_storage
|
||||||
|
*
|
||||||
|
* Return value: A newly allocated sockaddr_storage structure the caller must free
|
||||||
|
* or %NULL if @address did not point to a valid #GdmAddress.
|
||||||
|
**/
|
||||||
|
struct sockaddr_storage *
|
||||||
|
gdm_address_get_sockaddr_storage (GdmAddress *address)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage *ss;
|
||||||
|
|
||||||
|
g_return_val_if_fail (address != NULL, NULL);
|
||||||
|
g_return_val_if_fail (address->ss != NULL, NULL);
|
||||||
|
|
||||||
|
ss = g_memdup2 (address->ss, sizeof (struct sockaddr_storage));
|
||||||
|
|
||||||
|
return ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_storage *
|
||||||
|
gdm_address_peek_sockaddr_storage (GdmAddress *address)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (address != NULL, NULL);
|
||||||
|
|
||||||
|
return address->ss;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
v4_v4_equal (const struct sockaddr_in *a,
|
||||||
|
const struct sockaddr_in *b)
|
||||||
|
{
|
||||||
|
return a->sin_addr.s_addr == b->sin_addr.s_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
static gboolean
|
||||||
|
v6_v6_equal (struct sockaddr_in6 *a,
|
||||||
|
struct sockaddr_in6 *b)
|
||||||
|
{
|
||||||
|
return IN6_ARE_ADDR_EQUAL (&a->sin6_addr, &b->sin6_addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SA(__s) ((struct sockaddr *) __s)
|
||||||
|
#define SIN(__s) ((struct sockaddr_in *) __s)
|
||||||
|
#define SIN6(__s) ((struct sockaddr_in6 *) __s)
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_address_equal (GdmAddress *a,
|
||||||
|
GdmAddress *b)
|
||||||
|
{
|
||||||
|
guint8 fam_a;
|
||||||
|
guint8 fam_b;
|
||||||
|
|
||||||
|
g_return_val_if_fail (a != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (a->ss != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (b != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (b->ss != NULL, FALSE);
|
||||||
|
|
||||||
|
fam_a = a->ss->ss_family;
|
||||||
|
fam_b = b->ss->ss_family;
|
||||||
|
|
||||||
|
if (fam_a == AF_INET && fam_b == AF_INET) {
|
||||||
|
return v4_v4_equal (SIN (a->ss), SIN (b->ss));
|
||||||
|
}
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
else if (fam_a == AF_INET6 && fam_b == AF_INET6) {
|
||||||
|
return v6_v6_equal (SIN6 (a->ss), SIN6 (b->ss));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for debugging */
|
||||||
|
static const char *
|
||||||
|
address_family_str (GdmAddress *address)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
switch (address->ss->ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
str = "inet";
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
str = "inet6";
|
||||||
|
break;
|
||||||
|
case AF_UNIX:
|
||||||
|
str = "unix";
|
||||||
|
break;
|
||||||
|
case AF_UNSPEC:
|
||||||
|
str = "unspecified";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_address_debug (GdmAddress *address,
|
||||||
|
const char *host,
|
||||||
|
const char *port)
|
||||||
|
{
|
||||||
|
g_debug ("Address family:%d (%s) host:%s port:%s local:%d loopback:%d",
|
||||||
|
|
||||||
|
address->ss->ss_family,
|
||||||
|
address_family_str (address) ? address_family_str (address) : "(null)",
|
||||||
|
host ? host : "(null)",
|
||||||
|
port ? port : "(null)",
|
||||||
|
gdm_address_is_local (address),
|
||||||
|
gdm_address_is_loopback (address));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_address_debug (GdmAddress *address)
|
||||||
|
{
|
||||||
|
g_autofree char *hostname = NULL;
|
||||||
|
g_autofree char *host = NULL;
|
||||||
|
g_autofree char *port = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (address != NULL);
|
||||||
|
|
||||||
|
gdm_address_get_numeric_info (address, &host, &port);
|
||||||
|
|
||||||
|
_gdm_address_debug (address, host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_address_get_hostname (GdmAddress *address,
|
||||||
|
char **hostnamep)
|
||||||
|
{
|
||||||
|
char host [NI_MAXHOST];
|
||||||
|
int res;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (address != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (address->ss != NULL, FALSE);
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
host [0] = '\0';
|
||||||
|
res = getnameinfo ((const struct sockaddr *)address->ss,
|
||||||
|
(int) gdm_sockaddr_len (address->ss),
|
||||||
|
host, sizeof (host),
|
||||||
|
NULL, 0,
|
||||||
|
0);
|
||||||
|
if (res == 0) {
|
||||||
|
ret = TRUE;
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
const char *err_msg;
|
||||||
|
|
||||||
|
err_msg = gai_strerror (res);
|
||||||
|
g_warning ("Unable to lookup hostname: %s",
|
||||||
|
err_msg ? err_msg : "(null)");
|
||||||
|
_gdm_address_debug (address, NULL, NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try numeric? */
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (hostnamep != NULL) {
|
||||||
|
*hostnamep = g_strdup (host);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_address_get_numeric_info (GdmAddress *address,
|
||||||
|
char **hostp,
|
||||||
|
char **servp)
|
||||||
|
{
|
||||||
|
char host [NI_MAXHOST];
|
||||||
|
char serv [NI_MAXSERV];
|
||||||
|
int res;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (address != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (address->ss != NULL, FALSE);
|
||||||
|
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
host [0] = '\0';
|
||||||
|
serv [0] = '\0';
|
||||||
|
res = getnameinfo ((const struct sockaddr *)address->ss,
|
||||||
|
(int) gdm_sockaddr_len (address->ss),
|
||||||
|
host, sizeof (host),
|
||||||
|
serv, sizeof (serv),
|
||||||
|
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||||
|
if (res != 0) {
|
||||||
|
const char *err_msg;
|
||||||
|
|
||||||
|
err_msg = gai_strerror (res);
|
||||||
|
g_warning ("Unable to lookup numeric info: %s",
|
||||||
|
err_msg ? err_msg : "(null)");
|
||||||
|
_gdm_address_debug (address, NULL, NULL);
|
||||||
|
} else {
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servp != NULL) {
|
||||||
|
if (g_str_has_prefix (serv, "::ffff:")) {
|
||||||
|
*servp = g_strdup (serv + 7);
|
||||||
|
} else {
|
||||||
|
*servp = g_strdup (serv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hostp != NULL) {
|
||||||
|
if (g_str_has_prefix (host, "::ffff:")) {
|
||||||
|
*hostp = g_strdup (host + 7);
|
||||||
|
} else {
|
||||||
|
*hostp = g_strdup (host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_address_is_loopback (GdmAddress *address)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (address != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (address->ss != NULL, FALSE);
|
||||||
|
|
||||||
|
switch (address->ss->ss_family){
|
||||||
|
#ifdef AF_INET6
|
||||||
|
case AF_INET6:
|
||||||
|
return IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *)address->ss)->sin6_addr);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case AF_INET:
|
||||||
|
return (INADDR_LOOPBACK == htonl (((struct sockaddr_in *)address->ss)->sin_addr.s_addr));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_local_siocgifconf (GList **list)
|
||||||
|
{
|
||||||
|
struct ifconf ifc;
|
||||||
|
struct ifreq ifreq;
|
||||||
|
struct ifreq *ifr;
|
||||||
|
struct ifreq *the_end;
|
||||||
|
int sock;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
|
if ((sock = socket (PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||||
|
perror ("socket");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifc.ifc_len = sizeof (buf);
|
||||||
|
ifc.ifc_buf = buf;
|
||||||
|
if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0) {
|
||||||
|
perror ("SIOCGIFCONF");
|
||||||
|
close (sock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get IP address of each active IP network interface. */
|
||||||
|
the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
|
||||||
|
|
||||||
|
for (ifr = ifc.ifc_req; ifr < the_end; ifr++) {
|
||||||
|
if (ifr->ifr_addr.sa_family == AF_INET) {
|
||||||
|
/* IP net interface */
|
||||||
|
ifreq = *ifr;
|
||||||
|
|
||||||
|
if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
|
||||||
|
perror("SIOCGIFFLAGS");
|
||||||
|
} else if (ifreq.ifr_flags & IFF_UP) { /* active interface */
|
||||||
|
if (ioctl (sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
|
||||||
|
perror("SIOCGIFADDR");
|
||||||
|
} else {
|
||||||
|
GdmAddress *address;
|
||||||
|
address = gdm_address_new_from_sockaddr ((struct sockaddr *)&ifreq.ifr_addr,
|
||||||
|
sizeof (struct sockaddr));
|
||||||
|
|
||||||
|
*list = g_list_append (*list, address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Support for variable-length addresses. */
|
||||||
|
#ifdef HAS_SA_LEN
|
||||||
|
ifr = (struct ifreq *) ((caddr_t) ifr
|
||||||
|
+ ifr->ifr_addr.sa_len - sizeof(struct sockaddr));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
close (sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_local_addrinfo (GList **list)
|
||||||
|
{
|
||||||
|
struct ifaddrs *interface_addresses;
|
||||||
|
struct ifaddrs *interface_address;
|
||||||
|
|
||||||
|
if (getifaddrs (&interface_addresses) < 0) {
|
||||||
|
g_debug ("Could not get local interface addresses: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (interface_address = interface_addresses; interface_address != NULL; interface_address = interface_address->ifa_next) {
|
||||||
|
GdmAddress *address;
|
||||||
|
int family;
|
||||||
|
|
||||||
|
if (interface_address->ifa_addr == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
family = interface_address->ifa_addr->sa_family;
|
||||||
|
|
||||||
|
if (family != AF_INET && family != AF_INET6)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_debug ("Local interface %s found (family: %s)\n",
|
||||||
|
interface_address->ifa_name,
|
||||||
|
family == AF_INET ? "AF_INET" : "AF_INET6");
|
||||||
|
|
||||||
|
address = gdm_address_new_from_sockaddr (interface_address->ifa_addr,
|
||||||
|
(family == AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6));
|
||||||
|
*list = g_list_append (*list, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
freeifaddrs (interface_addresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GList *
|
||||||
|
gdm_address_peek_local_list (void)
|
||||||
|
{
|
||||||
|
static GList *list = NULL;
|
||||||
|
static time_t last_time = 0;
|
||||||
|
|
||||||
|
/* Don't check more then every 5 seconds */
|
||||||
|
if (last_time + 5 > time (NULL)) {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_foreach (list, (GFunc)gdm_address_free, NULL);
|
||||||
|
g_list_free (list);
|
||||||
|
list = NULL;
|
||||||
|
|
||||||
|
last_time = time (NULL);
|
||||||
|
|
||||||
|
add_local_siocgifconf (&list);
|
||||||
|
add_local_addrinfo (&list);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_address_is_local (GdmAddress *address)
|
||||||
|
{
|
||||||
|
const GList *list;
|
||||||
|
|
||||||
|
g_return_val_if_fail (address != NULL, FALSE);
|
||||||
|
|
||||||
|
if (gdm_address_is_loopback (address)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = gdm_address_peek_local_list ();
|
||||||
|
|
||||||
|
while (list != NULL) {
|
||||||
|
GdmAddress *addr = list->data;
|
||||||
|
|
||||||
|
if (gdm_address_equal (address, addr)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdm_address_copy:
|
||||||
|
* @address: A #GdmAddress.
|
||||||
|
*
|
||||||
|
* Duplicates @address.
|
||||||
|
*
|
||||||
|
* Return value: Duplicated @address or %NULL if @address was not valid.
|
||||||
|
**/
|
||||||
|
GdmAddress *
|
||||||
|
gdm_address_copy (GdmAddress *address)
|
||||||
|
{
|
||||||
|
GdmAddress *addr;
|
||||||
|
|
||||||
|
g_return_val_if_fail (address != NULL, NULL);
|
||||||
|
|
||||||
|
addr = g_new0 (GdmAddress, 1);
|
||||||
|
addr->ss = g_memdup2 (address->ss, sizeof (struct sockaddr_storage));
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdm_address_free:
|
||||||
|
* @address: A #GdmAddress.
|
||||||
|
*
|
||||||
|
* Frees the memory allocated for @address.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
gdm_address_free (GdmAddress *address)
|
||||||
|
{
|
||||||
|
g_return_if_fail (address != NULL);
|
||||||
|
|
||||||
|
g_free (address->ss);
|
||||||
|
g_free (address);
|
||||||
|
}
|
||||||
|
|
73
common/gdm-address.h
Normal file
73
common/gdm-address.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_ADDRESS_H
|
||||||
|
#define __GDM_ADDRESS_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#ifndef G_OS_WIN32
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#else
|
||||||
|
#include <winsock2.h>
|
||||||
|
#undef interface
|
||||||
|
#endif
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_ADDRESS (gdm_address_get_type ())
|
||||||
|
#define gdm_sockaddr_len(sa) ((sa)->ss_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
|
||||||
|
|
||||||
|
typedef struct _GdmAddress GdmAddress;
|
||||||
|
|
||||||
|
GType gdm_address_get_type (void);
|
||||||
|
|
||||||
|
GdmAddress * gdm_address_new_from_sockaddr (struct sockaddr *sa,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
int gdm_address_get_family_type (GdmAddress *address);
|
||||||
|
struct sockaddr_storage *gdm_address_get_sockaddr_storage (GdmAddress *address);
|
||||||
|
struct sockaddr_storage *gdm_address_peek_sockaddr_storage (GdmAddress *address);
|
||||||
|
|
||||||
|
gboolean gdm_address_get_hostname (GdmAddress *address,
|
||||||
|
char **hostname);
|
||||||
|
gboolean gdm_address_get_numeric_info (GdmAddress *address,
|
||||||
|
char **numeric_hostname,
|
||||||
|
char **service);
|
||||||
|
gboolean gdm_address_is_local (GdmAddress *address);
|
||||||
|
gboolean gdm_address_is_loopback (GdmAddress *address);
|
||||||
|
|
||||||
|
gboolean gdm_address_equal (GdmAddress *a,
|
||||||
|
GdmAddress *b);
|
||||||
|
|
||||||
|
GdmAddress * gdm_address_copy (GdmAddress *address);
|
||||||
|
void gdm_address_free (GdmAddress *address);
|
||||||
|
|
||||||
|
|
||||||
|
void gdm_address_debug (GdmAddress *address);
|
||||||
|
|
||||||
|
const GList * gdm_address_peek_local_list (void);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_ADDRESS_H */
|
1122
common/gdm-common.c
Normal file
1122
common/gdm-common.c
Normal file
File diff suppressed because it is too large
Load diff
110
common/gdm-common.h
Normal file
110
common/gdm-common.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GDM_COMMON_H
|
||||||
|
#define _GDM_COMMON_H
|
||||||
|
|
||||||
|
#include <glib-unix.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define REGISTER_SESSION_TIMEOUT 10
|
||||||
|
|
||||||
|
#define VE_IGNORE_EINTR(expr) \
|
||||||
|
do { \
|
||||||
|
errno = 0; \
|
||||||
|
expr; \
|
||||||
|
} while G_UNLIKELY (errno == EINTR);
|
||||||
|
|
||||||
|
#define GDM_SYSTEMD_SESSION_REQUIRE_ONLINE 0
|
||||||
|
|
||||||
|
GQuark gdm_common_error_quark (void);
|
||||||
|
#define GDM_COMMON_ERROR gdm_common_error_quark()
|
||||||
|
|
||||||
|
typedef char * (*GdmExpandVarFunc) (const char *var,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
typedef void (*GdmLoadEnvVarFunc) (const char *var,
|
||||||
|
const char *value,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
int gdm_wait_on_pid (int pid);
|
||||||
|
int gdm_wait_on_and_disown_pid (int pid,
|
||||||
|
int timeout);
|
||||||
|
int gdm_signal_pid (int pid,
|
||||||
|
int signal);
|
||||||
|
|
||||||
|
gboolean gdm_find_display_session (GPid pid,
|
||||||
|
const uid_t uid,
|
||||||
|
char **out_session_id,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gdm_get_pwent_for_name (const char *name,
|
||||||
|
struct passwd **pwentp);
|
||||||
|
|
||||||
|
gboolean gdm_clear_close_on_exec_flag (int fd);
|
||||||
|
|
||||||
|
char *gdm_generate_random_bytes (gsize size,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gdm_get_login_window_session_id (const char *seat_id,
|
||||||
|
char **session_id);
|
||||||
|
|
||||||
|
gboolean gdm_goto_login_session (GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GPtrArray *gdm_get_script_environment (const char *username,
|
||||||
|
const char *display_name,
|
||||||
|
const char *display_hostname,
|
||||||
|
const char *display_x11_authority_file);
|
||||||
|
|
||||||
|
gboolean gdm_run_script (const char *dir,
|
||||||
|
const char *username,
|
||||||
|
const char *display_name,
|
||||||
|
const char *display_hostname,
|
||||||
|
const char *display_x11_authority_file);
|
||||||
|
|
||||||
|
gboolean gdm_shell_var_is_valid_char (char c,
|
||||||
|
gboolean first);
|
||||||
|
|
||||||
|
char * gdm_shell_expand (const char *str,
|
||||||
|
GdmExpandVarFunc expand_func,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean gdm_activate_session_by_id (GDBusConnection *connection,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
const char *seat_id,
|
||||||
|
const char *session_id);
|
||||||
|
|
||||||
|
gboolean gdm_terminate_session_by_id (GDBusConnection *connection,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
const char *session_id);
|
||||||
|
|
||||||
|
void gdm_load_env_d (GdmLoadEnvVarFunc load_env_func,
|
||||||
|
GdmExpandVarFunc expand_func,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _GDM_COMMON_H */
|
145
common/gdm-log.c
Normal file
145
common/gdm-log.c
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Authors: William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include "gdm-log.h"
|
||||||
|
|
||||||
|
static gboolean initialized = FALSE;
|
||||||
|
static gboolean is_sd_booted = FALSE;
|
||||||
|
static gboolean debug_enabled = FALSE;
|
||||||
|
|
||||||
|
static gint
|
||||||
|
get_syslog_priority_from_log_level (GLogLevelFlags log_level)
|
||||||
|
{
|
||||||
|
switch (log_level & G_LOG_LEVEL_MASK) {
|
||||||
|
case G_LOG_FLAG_FATAL:
|
||||||
|
return LOG_EMERG;
|
||||||
|
case G_LOG_LEVEL_ERROR:
|
||||||
|
/* fatal error - a critical error, in the syslog world */
|
||||||
|
return LOG_CRIT;
|
||||||
|
case G_LOG_LEVEL_CRITICAL:
|
||||||
|
/* critical warning - an error, in the syslog world */
|
||||||
|
return LOG_ERR;
|
||||||
|
case G_LOG_LEVEL_WARNING:
|
||||||
|
case G_LOG_LEVEL_MESSAGE:
|
||||||
|
return LOG_NOTICE;
|
||||||
|
case G_LOG_LEVEL_INFO:
|
||||||
|
return LOG_INFO;
|
||||||
|
case G_LOG_LEVEL_DEBUG:
|
||||||
|
default:
|
||||||
|
return LOG_DEBUG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_log_default_handler (const gchar *log_domain,
|
||||||
|
GLogLevelFlags log_level,
|
||||||
|
const gchar *message,
|
||||||
|
gpointer unused_data)
|
||||||
|
{
|
||||||
|
int priority;
|
||||||
|
|
||||||
|
gdm_log_init ();
|
||||||
|
|
||||||
|
if ((log_level & G_LOG_LEVEL_MASK) == G_LOG_LEVEL_DEBUG &&
|
||||||
|
!debug_enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process the message prefix and priority */
|
||||||
|
priority = get_syslog_priority_from_log_level (log_level);
|
||||||
|
|
||||||
|
if (is_sd_booted) {
|
||||||
|
fprintf (stderr,
|
||||||
|
"<%d>%s%s%s\n",
|
||||||
|
priority,
|
||||||
|
log_domain != NULL? log_domain : "",
|
||||||
|
log_domain != NULL? ": " : "",
|
||||||
|
message);
|
||||||
|
fflush (stderr);
|
||||||
|
} else {
|
||||||
|
syslog (priority,
|
||||||
|
"%s%s%s\n",
|
||||||
|
log_domain != NULL? log_domain : "",
|
||||||
|
log_domain != NULL? ": " : "",
|
||||||
|
message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_toggle_debug (void)
|
||||||
|
{
|
||||||
|
gdm_log_set_debug (!debug_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_set_debug (gboolean debug)
|
||||||
|
{
|
||||||
|
g_assert (initialized);
|
||||||
|
if (debug_enabled == debug) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
debug_enabled = debug;
|
||||||
|
g_debug ("Enabling debugging");
|
||||||
|
} else {
|
||||||
|
g_debug ("Disabling debugging");
|
||||||
|
debug_enabled = debug;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_init (void)
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
initialized = TRUE;
|
||||||
|
|
||||||
|
g_log_set_default_handler (gdm_log_default_handler, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_log_shutdown (void)
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
if (!is_sd_booted)
|
||||||
|
closelog ();
|
||||||
|
initialized = FALSE;
|
||||||
|
}
|
||||||
|
|
38
common/gdm-log.h
Normal file
38
common/gdm-log.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Authors: William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_LOG_H
|
||||||
|
#define __GDM_LOG_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void gdm_log_set_debug (gboolean debug);
|
||||||
|
void gdm_log_toggle_debug (void);
|
||||||
|
void gdm_log_init (void);
|
||||||
|
void gdm_log_shutdown (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_LOG_H */
|
72
common/gdm-profile.c
Normal file
72
common/gdm-profile.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Authors: William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include "gdm-profile.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdm_profile_log (const char *func,
|
||||||
|
const char *note,
|
||||||
|
const char *format,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
g_autofree char *str = NULL;
|
||||||
|
g_autofree char *formatted = NULL;
|
||||||
|
const char *prgname;
|
||||||
|
|
||||||
|
if (format == NULL) {
|
||||||
|
formatted = g_strdup ("");
|
||||||
|
} else {
|
||||||
|
va_start (args, format);
|
||||||
|
formatted = g_strdup_vprintf (format, args);
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
|
||||||
|
prgname = g_get_prgname();
|
||||||
|
|
||||||
|
if (func != NULL) {
|
||||||
|
str = g_strdup_printf ("MARK: %s %s: %s %s",
|
||||||
|
prgname ? prgname : "(null)",
|
||||||
|
func,
|
||||||
|
note ? note : "",
|
||||||
|
formatted);
|
||||||
|
} else {
|
||||||
|
str = g_strdup_printf ("MARK: %s: %s %s",
|
||||||
|
prgname ? prgname : "(null)",
|
||||||
|
note ? note : "",
|
||||||
|
formatted);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_access (str, F_OK);
|
||||||
|
}
|
53
common/gdm-profile.h
Normal file
53
common/gdm-profile.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Authors: William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_PROFILE_H
|
||||||
|
#define __GDM_PROFILE_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#ifdef ENABLE_PROFILING
|
||||||
|
#ifdef G_HAVE_ISO_VARARGS
|
||||||
|
#define gdm_profile_start(...) _gdm_profile_log (G_STRFUNC, "start", __VA_ARGS__)
|
||||||
|
#define gdm_profile_end(...) _gdm_profile_log (G_STRFUNC, "end", __VA_ARGS__)
|
||||||
|
#define gdm_profile_msg(...) _gdm_profile_log (NULL, NULL, __VA_ARGS__)
|
||||||
|
#elif defined(G_HAVE_GNUC_VARARGS)
|
||||||
|
#define gdm_profile_start(format...) _gdm_profile_log (G_STRFUNC, "start", format)
|
||||||
|
#define gdm_profile_end(format...) _gdm_profile_log (G_STRFUNC, "end", format)
|
||||||
|
#define gdm_profile_msg(format...) _gdm_profile_log (NULL, NULL, format)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define gdm_profile_start(...)
|
||||||
|
#define gdm_profile_end(...)
|
||||||
|
#define gdm_profile_msg(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void _gdm_profile_log (const char *func,
|
||||||
|
const char *note,
|
||||||
|
const char *format,
|
||||||
|
...) G_GNUC_PRINTF (3, 4);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_PROFILE_H */
|
169
common/gdm-settings-backend.c
Normal file
169
common/gdm-settings-backend.c
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-settings-backend.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VALUE_CHANGED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
static void gdm_settings_backend_class_init (GdmSettingsBackendClass *klass);
|
||||||
|
static void gdm_settings_backend_init (GdmSettingsBackend *settings_backend);
|
||||||
|
static void gdm_settings_backend_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_ABSTRACT_TYPE (GdmSettingsBackend, gdm_settings_backend, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gdm_settings_backend_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark ret = 0;
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = g_quark_from_static_string ("gdm_settings_backend_error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_settings_backend_real_get_value (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
char **value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (settings_backend), FALSE);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_settings_backend_real_set_value (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
const char *value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (settings_backend), FALSE);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_backend_get_value (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
char **value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (settings_backend), FALSE);
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
g_object_ref (settings_backend);
|
||||||
|
ret = GDM_SETTINGS_BACKEND_GET_CLASS (settings_backend)->get_value (settings_backend, key, value, error);
|
||||||
|
g_object_unref (settings_backend);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_backend_set_value (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
const char *value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (settings_backend), FALSE);
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
g_object_ref (settings_backend);
|
||||||
|
ret = GDM_SETTINGS_BACKEND_GET_CLASS (settings_backend)->set_value (settings_backend, key, value, error);
|
||||||
|
g_object_unref (settings_backend);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_settings_backend_value_changed (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
const char *old_value,
|
||||||
|
const char *new_value)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SETTINGS_BACKEND (settings_backend));
|
||||||
|
|
||||||
|
g_signal_emit (settings_backend, signals[VALUE_CHANGED], 0, key, old_value, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_backend_class_init (GdmSettingsBackendClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_settings_backend_finalize;
|
||||||
|
|
||||||
|
klass->get_value = gdm_settings_backend_real_get_value;
|
||||||
|
klass->set_value = gdm_settings_backend_real_set_value;
|
||||||
|
|
||||||
|
signals [VALUE_CHANGED] =
|
||||||
|
g_signal_new ("value-changed",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (GdmSettingsBackendClass, value_changed),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_generic,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
3,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_backend_init (GdmSettingsBackend *settings_backend)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_backend_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SETTINGS_BACKEND (object));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_settings_backend_parent_class)->finalize (object);
|
||||||
|
}
|
79
common/gdm-settings-backend.h
Normal file
79
common/gdm-settings-backend.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_SETTINGS_BACKEND_H
|
||||||
|
#define __GDM_SETTINGS_BACKEND_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SETTINGS_BACKEND (gdm_settings_backend_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GdmSettingsBackend, gdm_settings_backend, GDM, SETTINGS_BACKEND, GObject)
|
||||||
|
|
||||||
|
struct _GdmSettingsBackendClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/* methods */
|
||||||
|
gboolean (*get_value) (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
char **value,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*set_value) (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
const char *value,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
void (* value_changed) (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
const char *old_value,
|
||||||
|
const char **new_value);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_SETTINGS_BACKEND_ERROR_GENERAL,
|
||||||
|
GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND
|
||||||
|
} GdmSettingsBackendError;
|
||||||
|
|
||||||
|
#define GDM_SETTINGS_BACKEND_ERROR gdm_settings_backend_error_quark ()
|
||||||
|
|
||||||
|
GQuark gdm_settings_backend_error_quark (void);
|
||||||
|
|
||||||
|
gboolean gdm_settings_backend_get_value (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
char **value,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_settings_backend_set_value (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
const char *value,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gdm_settings_backend_value_changed (GdmSettingsBackend *settings_backend,
|
||||||
|
const char *key,
|
||||||
|
const char *old_value,
|
||||||
|
const char *new_value);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_SETTINGS_BACKEND_H */
|
399
common/gdm-settings-desktop-backend.c
Normal file
399
common/gdm-settings-desktop-backend.c
Normal file
|
@ -0,0 +1,399 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-settings-desktop-backend.h"
|
||||||
|
|
||||||
|
struct _GdmSettingsDesktopBackend
|
||||||
|
{
|
||||||
|
GdmSettingsBackend parent;
|
||||||
|
|
||||||
|
char *filename;
|
||||||
|
GKeyFile *key_file;
|
||||||
|
gboolean dirty;
|
||||||
|
guint save_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_FILENAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_settings_desktop_backend_class_init (GdmSettingsDesktopBackendClass *klass);
|
||||||
|
static void gdm_settings_desktop_backend_init (GdmSettingsDesktopBackend *settings_desktop_backend);
|
||||||
|
static void gdm_settings_desktop_backend_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmSettingsDesktopBackend, gdm_settings_desktop_backend, GDM_TYPE_SETTINGS_BACKEND)
|
||||||
|
|
||||||
|
static void
|
||||||
|
_gdm_settings_desktop_backend_set_file_name (GdmSettingsDesktopBackend *backend,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
gboolean res;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autofree char *contents = NULL;
|
||||||
|
|
||||||
|
g_free (backend->filename);
|
||||||
|
backend->filename = g_strdup (filename);
|
||||||
|
|
||||||
|
backend->key_file = g_key_file_new ();
|
||||||
|
|
||||||
|
res = g_key_file_load_from_file (backend->key_file,
|
||||||
|
backend->filename,
|
||||||
|
G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
|
||||||
|
&error);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to load file '%s': %s", backend->filename, error->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
contents = g_key_file_to_data (backend->key_file, NULL, NULL);
|
||||||
|
|
||||||
|
if (contents != NULL) {
|
||||||
|
g_debug ("GdmSettings: %s is:\n%s\n", backend->filename, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_desktop_backend_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSettingsDesktopBackend *self;
|
||||||
|
|
||||||
|
self = GDM_SETTINGS_DESKTOP_BACKEND (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_FILENAME:
|
||||||
|
_gdm_settings_desktop_backend_set_file_name (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_desktop_backend_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSettingsDesktopBackend *self;
|
||||||
|
|
||||||
|
self = GDM_SETTINGS_DESKTOP_BACKEND (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_FILENAME:
|
||||||
|
g_value_set_string (value, self->filename);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_key_string (const char *keystring,
|
||||||
|
char **group,
|
||||||
|
char **key,
|
||||||
|
char **locale,
|
||||||
|
char **value)
|
||||||
|
{
|
||||||
|
g_auto(GStrv) split1 = NULL;
|
||||||
|
g_auto(GStrv) split2 = NULL;
|
||||||
|
char *g;
|
||||||
|
char *k;
|
||||||
|
char *l;
|
||||||
|
char *v;
|
||||||
|
char *tmp1;
|
||||||
|
char *tmp2;
|
||||||
|
|
||||||
|
g_return_val_if_fail (keystring != NULL, FALSE);
|
||||||
|
|
||||||
|
g = k = v = l = NULL;
|
||||||
|
|
||||||
|
if (group != NULL) {
|
||||||
|
*group = g;
|
||||||
|
}
|
||||||
|
if (key != NULL) {
|
||||||
|
*key = k;
|
||||||
|
}
|
||||||
|
if (locale != NULL) {
|
||||||
|
*locale = l;
|
||||||
|
}
|
||||||
|
if (value != NULL) {
|
||||||
|
*value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*g_debug ("Attempting to parse key string: %s", keystring);*/
|
||||||
|
|
||||||
|
split1 = g_strsplit (keystring, "/", 2);
|
||||||
|
if (split1 == NULL
|
||||||
|
|| split1 [0] == NULL
|
||||||
|
|| split1 [1] == NULL
|
||||||
|
|| split1 [0][0] == '\0'
|
||||||
|
|| split1 [1][0] == '\0') {
|
||||||
|
g_warning ("GdmSettingsDesktopBackend: invalid key: %s", keystring);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g = split1 [0];
|
||||||
|
|
||||||
|
split2 = g_strsplit (split1 [1], "=", 2);
|
||||||
|
if (split2 == NULL) {
|
||||||
|
k = split1 [1];
|
||||||
|
} else {
|
||||||
|
k = split2 [0];
|
||||||
|
v = split2 [1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* trim off the locale */
|
||||||
|
tmp1 = strchr (k, '[');
|
||||||
|
tmp2 = strchr (k, ']');
|
||||||
|
if (tmp1 != NULL && tmp2 != NULL && tmp2 > tmp1) {
|
||||||
|
l = g_strndup (tmp1 + 1, tmp2 - tmp1 - 1);
|
||||||
|
*tmp1 = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group != NULL) {
|
||||||
|
*group = g_strdup (g);
|
||||||
|
}
|
||||||
|
if (key != NULL) {
|
||||||
|
*key = g_strdup (k);
|
||||||
|
}
|
||||||
|
if (locale != NULL) {
|
||||||
|
*locale = g_strdup (l);
|
||||||
|
}
|
||||||
|
if (value != NULL) {
|
||||||
|
*value = g_strdup (v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_settings_desktop_backend_get_value (GdmSettingsBackend *backend,
|
||||||
|
const char *key,
|
||||||
|
char **value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
g_autofree char *val = NULL;
|
||||||
|
g_autofree char *g = NULL;
|
||||||
|
g_autofree char *k = NULL;
|
||||||
|
g_autofree char *l = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (backend), FALSE);
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
*value = NULL;
|
||||||
|
|
||||||
|
/*GDM_SETTINGS_BACKEND_CLASS (gdm_settings_desktop_backend_parent_class)->get_value (display);*/
|
||||||
|
if (! parse_key_string (key, &g, &k, &l, NULL)) {
|
||||||
|
g_set_error (error, GDM_SETTINGS_BACKEND_ERROR, GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND, "Key not found");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*g_debug ("Getting key: %s %s %s", g, k, l);*/
|
||||||
|
val = g_key_file_get_value (GDM_SETTINGS_DESKTOP_BACKEND (backend)->key_file,
|
||||||
|
g,
|
||||||
|
k,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL) {
|
||||||
|
g_set_error (error, GDM_SETTINGS_BACKEND_ERROR, GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND, "Key not found");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = g_strdup (val);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
save_settings (GdmSettingsDesktopBackend *backend)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
g_autofree char *contents = NULL;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
if (! backend->dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("Saving settings to %s", backend->filename);
|
||||||
|
|
||||||
|
contents = g_key_file_to_data (backend->key_file, &length, &local_error);
|
||||||
|
if (local_error != NULL) {
|
||||||
|
g_warning ("Unable to save settings: %s", local_error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_file_set_contents (backend->filename,
|
||||||
|
contents,
|
||||||
|
length,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL) {
|
||||||
|
g_warning ("Unable to save settings: %s", local_error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->dirty = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
save_settings_timer (GdmSettingsDesktopBackend *backend)
|
||||||
|
{
|
||||||
|
save_settings (backend);
|
||||||
|
backend->save_id = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
queue_save (GdmSettingsDesktopBackend *backend)
|
||||||
|
{
|
||||||
|
if (! backend->dirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend->save_id != 0) {
|
||||||
|
/* already pending */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->save_id = g_timeout_add_seconds (5, (GSourceFunc)save_settings_timer, backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_settings_desktop_backend_set_value (GdmSettingsBackend *backend,
|
||||||
|
const char *key,
|
||||||
|
const char *value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autofree char *old_val = NULL;
|
||||||
|
g_autofree char *g = NULL;
|
||||||
|
g_autofree char *k = NULL;
|
||||||
|
g_autofree char *l = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (backend), FALSE);
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
/*GDM_SETTINGS_BACKEND_CLASS (gdm_settings_desktop_backend_parent_class)->get_value (display);*/
|
||||||
|
if (! parse_key_string (key, &g, &k, &l, NULL)) {
|
||||||
|
g_set_error (error, GDM_SETTINGS_BACKEND_ERROR, GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND, "Key not found");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_val = g_key_file_get_value (GDM_SETTINGS_DESKTOP_BACKEND (backend)->key_file,
|
||||||
|
g,
|
||||||
|
k,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/*g_debug ("Setting key: %s %s %s", g, k, l);*/
|
||||||
|
g_key_file_set_value (GDM_SETTINGS_DESKTOP_BACKEND (backend)->key_file,
|
||||||
|
g,
|
||||||
|
k,
|
||||||
|
value);
|
||||||
|
|
||||||
|
GDM_SETTINGS_DESKTOP_BACKEND (backend)->dirty = TRUE;
|
||||||
|
queue_save (GDM_SETTINGS_DESKTOP_BACKEND (backend));
|
||||||
|
|
||||||
|
gdm_settings_backend_value_changed (backend, key, old_val, value);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_desktop_backend_class_init (GdmSettingsDesktopBackendClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GdmSettingsBackendClass *backend_class = GDM_SETTINGS_BACKEND_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_settings_desktop_backend_get_property;
|
||||||
|
object_class->set_property = gdm_settings_desktop_backend_set_property;
|
||||||
|
object_class->finalize = gdm_settings_desktop_backend_finalize;
|
||||||
|
|
||||||
|
backend_class->get_value = gdm_settings_desktop_backend_get_value;
|
||||||
|
backend_class->set_value = gdm_settings_desktop_backend_set_value;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_FILENAME,
|
||||||
|
g_param_spec_string ("filename",
|
||||||
|
"File Name",
|
||||||
|
"The name of the configuration file",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_desktop_backend_init (GdmSettingsDesktopBackend *backend)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_desktop_backend_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmSettingsDesktopBackend *backend;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_SETTINGS_DESKTOP_BACKEND (object));
|
||||||
|
|
||||||
|
backend = GDM_SETTINGS_DESKTOP_BACKEND (object);
|
||||||
|
|
||||||
|
save_settings (backend);
|
||||||
|
g_key_file_free (backend->key_file);
|
||||||
|
g_free (backend->filename);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_settings_desktop_backend_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmSettingsBackend *
|
||||||
|
gdm_settings_desktop_backend_new (const char* filename)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
g_return_val_if_fail (filename != NULL, NULL);
|
||||||
|
|
||||||
|
if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_SETTINGS_DESKTOP_BACKEND,
|
||||||
|
"filename", filename,
|
||||||
|
NULL);
|
||||||
|
return GDM_SETTINGS_BACKEND (object);
|
||||||
|
}
|
37
common/gdm-settings-desktop-backend.h
Normal file
37
common/gdm-settings-desktop-backend.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_SETTINGS_DESKTOP_BACKEND_H
|
||||||
|
#define __GDM_SETTINGS_DESKTOP_BACKEND_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gdm-settings-backend.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SETTINGS_DESKTOP_BACKEND (gdm_settings_desktop_backend_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSettingsDesktopBackend, gdm_settings_desktop_backend, GDM, SETTINGS_DESKTOP_BACKEND, GdmSettingsBackend)
|
||||||
|
|
||||||
|
GdmSettingsBackend *gdm_settings_desktop_backend_new (const char* filename);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_SETTINGS_DESKTOP_BACKEND_H */
|
244
common/gdm-settings-direct.c
Normal file
244
common/gdm-settings-direct.c
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-settings.h"
|
||||||
|
#include "gdm-settings-utils.h"
|
||||||
|
#include "gdm-settings-direct.h"
|
||||||
|
|
||||||
|
static GHashTable *schemas;
|
||||||
|
static GdmSettings *settings_object;
|
||||||
|
|
||||||
|
static GdmSettingsEntry *
|
||||||
|
get_entry_for_key (const char *key)
|
||||||
|
{
|
||||||
|
GdmSettingsEntry *entry;
|
||||||
|
|
||||||
|
entry = g_hash_table_lookup (schemas, key);
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_signature (GdmSettingsEntry *entry,
|
||||||
|
const char *signature)
|
||||||
|
{
|
||||||
|
const char *sig;
|
||||||
|
|
||||||
|
sig = gdm_settings_entry_get_signature (entry);
|
||||||
|
|
||||||
|
g_assert (sig != NULL);
|
||||||
|
g_assert (signature != NULL);
|
||||||
|
g_assert (strcmp (signature, sig) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_value (const char *key,
|
||||||
|
char **value)
|
||||||
|
{
|
||||||
|
g_autofree char *str = NULL;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
res = gdm_settings_get_value (settings_object, key, &str, NULL);
|
||||||
|
if (! res) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value != NULL) {
|
||||||
|
*value = g_strdup (str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_direct_get_int (const char *key,
|
||||||
|
int *value)
|
||||||
|
{
|
||||||
|
GdmSettingsEntry *entry;
|
||||||
|
gboolean ret;
|
||||||
|
gboolean res;
|
||||||
|
g_autofree char *str = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
entry = get_entry_for_key (key);
|
||||||
|
g_assert (entry != NULL);
|
||||||
|
|
||||||
|
assert_signature (entry, "i");
|
||||||
|
|
||||||
|
res = get_value (key, &str);
|
||||||
|
|
||||||
|
if (! res) {
|
||||||
|
/* use the default */
|
||||||
|
str = g_strdup (gdm_settings_entry_get_default_value (entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gdm_settings_parse_value_as_integer (str, value);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_direct_get_uint (const char *key,
|
||||||
|
uint *value)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
int intvalue;
|
||||||
|
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
ret = gdm_settings_direct_get_int (key, &intvalue);
|
||||||
|
|
||||||
|
if (intvalue >= 0)
|
||||||
|
*value = intvalue;
|
||||||
|
else
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_direct_get_boolean (const char *key,
|
||||||
|
gboolean *value)
|
||||||
|
{
|
||||||
|
GdmSettingsEntry *entry;
|
||||||
|
gboolean ret;
|
||||||
|
gboolean res;
|
||||||
|
g_autofree char *str = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
entry = get_entry_for_key (key);
|
||||||
|
g_assert (entry != NULL);
|
||||||
|
|
||||||
|
assert_signature (entry, "b");
|
||||||
|
|
||||||
|
res = get_value (key, &str);
|
||||||
|
|
||||||
|
if (! res) {
|
||||||
|
/* use the default */
|
||||||
|
str = g_strdup (gdm_settings_entry_get_default_value (entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gdm_settings_parse_value_as_boolean (str, value);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_direct_get_string (const char *key,
|
||||||
|
char **value)
|
||||||
|
{
|
||||||
|
GdmSettingsEntry *entry;
|
||||||
|
gboolean ret;
|
||||||
|
gboolean res;
|
||||||
|
g_autofree char *str = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
entry = get_entry_for_key (key);
|
||||||
|
g_assert (entry != NULL);
|
||||||
|
|
||||||
|
assert_signature (entry, "s");
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
res = get_value (key, &str);
|
||||||
|
|
||||||
|
if (! res) {
|
||||||
|
/* use the default */
|
||||||
|
str = g_strdup (gdm_settings_entry_get_default_value (entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = g_strdup (str);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hashify_list (GdmSettingsEntry *entry,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
g_hash_table_insert (schemas, g_strdup (gdm_settings_entry_get_key (entry)), entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_direct_init (GdmSettings *settings,
|
||||||
|
const char *file,
|
||||||
|
const char *root)
|
||||||
|
{
|
||||||
|
GSList *list;
|
||||||
|
|
||||||
|
g_return_val_if_fail (file != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (root != NULL, FALSE);
|
||||||
|
|
||||||
|
g_debug ("Settings Direct Init");
|
||||||
|
if (schemas != NULL) {
|
||||||
|
g_hash_table_unref (schemas);
|
||||||
|
schemas = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! gdm_settings_parse_schemas (file, root, &list)) {
|
||||||
|
g_warning ("Unable to parse schemas");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
schemas = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)gdm_settings_entry_free);
|
||||||
|
g_slist_foreach (list, (GFunc)hashify_list, NULL);
|
||||||
|
|
||||||
|
settings_object = settings;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_settings_direct_reload (void)
|
||||||
|
{
|
||||||
|
if (!settings_object)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdm_settings_reload (settings_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_settings_direct_shutdown (void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
48
common/gdm-settings-direct.h
Normal file
48
common/gdm-settings-direct.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_SETTINGS_DIRECT_H
|
||||||
|
#define __GDM_SETTINGS_DIRECT_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gdm-settings.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
gboolean gdm_settings_direct_init (GdmSettings *settings,
|
||||||
|
const char *schemas_file,
|
||||||
|
const char *root);
|
||||||
|
|
||||||
|
void gdm_settings_direct_reload (void);
|
||||||
|
void gdm_settings_direct_shutdown (void);
|
||||||
|
|
||||||
|
gboolean gdm_settings_direct_get_int (const char *key,
|
||||||
|
int *value);
|
||||||
|
gboolean gdm_settings_direct_get_uint (const char *key,
|
||||||
|
uint *value);
|
||||||
|
gboolean gdm_settings_direct_get_boolean (const char *key,
|
||||||
|
gboolean *value);
|
||||||
|
gboolean gdm_settings_direct_get_string (const char *key,
|
||||||
|
char **value);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_SETTINGS_DIRECT_H */
|
66
common/gdm-settings-keys.h
Normal file
66
common/gdm-settings-keys.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GDM_SETTINGS_KEYS_H
|
||||||
|
#define _GDM_SETTINGS_KEYS_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_KEY_USER "daemon/User"
|
||||||
|
#define GDM_KEY_GROUP "daemon/Group"
|
||||||
|
#define GDM_KEY_AUTO_LOGIN_ENABLE "daemon/AutomaticLoginEnable"
|
||||||
|
#define GDM_KEY_AUTO_LOGIN_USER "daemon/AutomaticLogin"
|
||||||
|
#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable"
|
||||||
|
#define GDM_KEY_TIMED_LOGIN_USER "daemon/TimedLogin"
|
||||||
|
#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay"
|
||||||
|
#define GDM_KEY_INITIAL_SETUP_ENABLE "daemon/InitialSetupEnable"
|
||||||
|
#define GDM_KEY_PREFERRED_DISPLAY_SERVER "daemon/PreferredDisplayServer"
|
||||||
|
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||||
|
#define GDM_KEY_WAYLAND_ENABLE "daemon/WaylandEnable"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_X11_SUPPORT
|
||||||
|
#define GDM_KEY_XORG_ENABLE "daemon/XorgEnable"
|
||||||
|
#endif
|
||||||
|
#define GDM_KEY_REMOTE_LOGIN_ENABLE "daemon/RemoteLoginEnable"
|
||||||
|
|
||||||
|
#define GDM_KEY_DEBUG "debug/Enable"
|
||||||
|
|
||||||
|
#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP"
|
||||||
|
#define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin"
|
||||||
|
|
||||||
|
#define GDM_KEY_XDMCP_ENABLE "xdmcp/Enable"
|
||||||
|
#define GDM_KEY_SHOW_LOCAL_GREETER "xdmcp/ShowLocalGreeter"
|
||||||
|
#define GDM_KEY_MAX_PENDING "xdmcp/MaxPending"
|
||||||
|
#define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions"
|
||||||
|
#define GDM_KEY_MAX_WAIT "xdmcp/MaxWait"
|
||||||
|
#define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost"
|
||||||
|
#define GDM_KEY_UDP_PORT "xdmcp/Port"
|
||||||
|
#define GDM_KEY_INDIRECT "xdmcp/HonorIndirect"
|
||||||
|
#define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect"
|
||||||
|
#define GDM_KEY_WILLING "xdmcp/Willing"
|
||||||
|
|
||||||
|
#define GDM_KEY_MULTICAST "chooser/Multicast"
|
||||||
|
#define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr"
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _GDM_SETTINGS_KEYS_H */
|
352
common/gdm-settings-utils.c
Normal file
352
common/gdm-settings-utils.c
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-settings-utils.h"
|
||||||
|
|
||||||
|
struct _GdmSettingsEntry
|
||||||
|
{
|
||||||
|
char *key;
|
||||||
|
char *signature;
|
||||||
|
char *default_value;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
GdmSettingsEntry *
|
||||||
|
gdm_settings_entry_new (void)
|
||||||
|
{
|
||||||
|
GdmSettingsEntry *entry = NULL;
|
||||||
|
|
||||||
|
entry = g_new0 (GdmSettingsEntry, 1);
|
||||||
|
entry->key = NULL;
|
||||||
|
entry->signature = NULL;
|
||||||
|
entry->value = NULL;
|
||||||
|
entry->default_value = NULL;
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gdm_settings_entry_get_key (GdmSettingsEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (entry != NULL, NULL);
|
||||||
|
|
||||||
|
return entry->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gdm_settings_entry_get_signature (GdmSettingsEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (entry != NULL, NULL);
|
||||||
|
|
||||||
|
return entry->signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gdm_settings_entry_get_default_value (GdmSettingsEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (entry != NULL, NULL);
|
||||||
|
|
||||||
|
return entry->default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
gdm_settings_entry_get_value (GdmSettingsEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (entry != NULL, NULL);
|
||||||
|
|
||||||
|
return entry->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_settings_entry_set_value (GdmSettingsEntry *entry,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
g_return_if_fail (entry != NULL);
|
||||||
|
|
||||||
|
g_free (entry->value);
|
||||||
|
entry->value = g_strdup (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_settings_entry_free (GdmSettingsEntry *entry)
|
||||||
|
{
|
||||||
|
g_return_if_fail (entry != NULL);
|
||||||
|
|
||||||
|
g_free (entry->key);
|
||||||
|
g_free (entry->signature);
|
||||||
|
g_free (entry->default_value);
|
||||||
|
g_free (entry->value);
|
||||||
|
g_free (entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GSList *list;
|
||||||
|
GdmSettingsEntry *entry;
|
||||||
|
gboolean in_key;
|
||||||
|
gboolean in_signature;
|
||||||
|
gboolean in_default;
|
||||||
|
} ParserInfo;
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_element_cb (GMarkupParseContext *ctx,
|
||||||
|
const char *element_name,
|
||||||
|
const char **attribute_names,
|
||||||
|
const char **attribute_values,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ParserInfo *info;
|
||||||
|
|
||||||
|
info = (ParserInfo *) user_data;
|
||||||
|
|
||||||
|
/*g_debug ("parsing start: '%s'", element_name);*/
|
||||||
|
|
||||||
|
if (strcmp (element_name, "schema") == 0) {
|
||||||
|
info->entry = gdm_settings_entry_new ();
|
||||||
|
} else if (strcmp (element_name, "key") == 0) {
|
||||||
|
info->in_key = TRUE;
|
||||||
|
} else if (strcmp (element_name, "signature") == 0) {
|
||||||
|
info->in_signature = TRUE;
|
||||||
|
} else if (strcmp (element_name, "default") == 0) {
|
||||||
|
info->in_default = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_schema_entry (ParserInfo *info)
|
||||||
|
{
|
||||||
|
/*g_debug ("Inserting entry %s", info->entry->key);*/
|
||||||
|
|
||||||
|
info->list = g_slist_prepend (info->list, info->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
end_element_cb (GMarkupParseContext *ctx,
|
||||||
|
const char *element_name,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ParserInfo *info;
|
||||||
|
|
||||||
|
info = (ParserInfo *) user_data;
|
||||||
|
|
||||||
|
/*g_debug ("parsing end: '%s'", element_name);*/
|
||||||
|
|
||||||
|
if (strcmp (element_name, "schema") == 0) {
|
||||||
|
add_schema_entry (info);
|
||||||
|
} else if (strcmp (element_name, "key") == 0) {
|
||||||
|
info->in_key = FALSE;
|
||||||
|
} else if (strcmp (element_name, "signature") == 0) {
|
||||||
|
info->in_signature = FALSE;
|
||||||
|
} else if (strcmp (element_name, "default") == 0) {
|
||||||
|
info->in_default = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
text_cb (GMarkupParseContext *ctx,
|
||||||
|
const char *text,
|
||||||
|
gsize text_len,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ParserInfo *info;
|
||||||
|
char *t;
|
||||||
|
|
||||||
|
info = (ParserInfo *) user_data;
|
||||||
|
|
||||||
|
t = g_strndup (text, text_len);
|
||||||
|
|
||||||
|
if (info->in_key) {
|
||||||
|
info->entry->key = g_strdup (t);
|
||||||
|
} else if (info->in_signature) {
|
||||||
|
info->entry->signature = g_strdup (t);
|
||||||
|
} else if (info->in_default) {
|
||||||
|
info->entry->default_value = g_strdup (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (t);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
error_cb (GMarkupParseContext *ctx,
|
||||||
|
GError *error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static GMarkupParser parser = {
|
||||||
|
start_element_cb,
|
||||||
|
end_element_cb,
|
||||||
|
text_cb,
|
||||||
|
NULL,
|
||||||
|
error_cb
|
||||||
|
};
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_parse_schemas (const char *file,
|
||||||
|
const char *root,
|
||||||
|
GSList **schemas)
|
||||||
|
{
|
||||||
|
GMarkupParseContext *ctx;
|
||||||
|
ParserInfo *info;
|
||||||
|
char *contents;
|
||||||
|
gsize len;
|
||||||
|
GError *error;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (file != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (root != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (schemas != NULL, FALSE);
|
||||||
|
|
||||||
|
contents = NULL;
|
||||||
|
error = NULL;
|
||||||
|
res = g_file_get_contents (file, &contents, &len, &error);
|
||||||
|
if (! res) {
|
||||||
|
g_warning ("Unable to read schemas file: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = g_new0 (ParserInfo, 1);
|
||||||
|
ctx = g_markup_parse_context_new (&parser, 0, info, NULL);
|
||||||
|
g_markup_parse_context_parse (ctx, contents, len, NULL);
|
||||||
|
|
||||||
|
*schemas = info->list;
|
||||||
|
|
||||||
|
g_markup_parse_context_free (ctx);
|
||||||
|
g_free (info);
|
||||||
|
g_free (contents);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_settings_parse_double_as_value (gdouble doubleval)
|
||||||
|
{
|
||||||
|
char result[G_ASCII_DTOSTR_BUF_SIZE];
|
||||||
|
|
||||||
|
g_ascii_dtostr (result, sizeof (result), doubleval);
|
||||||
|
|
||||||
|
return g_strdup (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_settings_parse_integer_as_value (int intval)
|
||||||
|
|
||||||
|
{
|
||||||
|
return g_strdup_printf ("%d", intval);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_settings_parse_boolean_as_value (gboolean boolval)
|
||||||
|
{
|
||||||
|
if (boolval) {
|
||||||
|
return g_strdup ("true");
|
||||||
|
} else {
|
||||||
|
return g_strdup ("false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* adapted from GKeyFile */
|
||||||
|
gboolean
|
||||||
|
gdm_settings_parse_value_as_boolean (const char *value,
|
||||||
|
gboolean *bool)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (bool != NULL, FALSE);
|
||||||
|
|
||||||
|
if (g_ascii_strcasecmp (value, "true") == 0 || strcmp (value, "1") == 0) {
|
||||||
|
*bool = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
} else if (g_ascii_strcasecmp (value, "false") == 0 || strcmp (value, "0") == 0) {
|
||||||
|
*bool = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_parse_value_as_integer (const char *value,
|
||||||
|
int *intval)
|
||||||
|
{
|
||||||
|
char *end_of_valid_int;
|
||||||
|
glong long_value;
|
||||||
|
gint int_value;
|
||||||
|
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (intval != NULL, FALSE);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
long_value = strtol (value, &end_of_valid_int, 10);
|
||||||
|
|
||||||
|
if (*value == '\0' || *end_of_valid_int != '\0') {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_value = long_value;
|
||||||
|
if (int_value != long_value || errno == ERANGE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*intval = int_value;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_parse_value_as_double (const char *value,
|
||||||
|
gdouble *doubleval)
|
||||||
|
{
|
||||||
|
char *end_of_valid_d;
|
||||||
|
gdouble double_value = 0;
|
||||||
|
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (doubleval != NULL, FALSE);
|
||||||
|
|
||||||
|
double_value = g_ascii_strtod (value, &end_of_valid_d);
|
||||||
|
|
||||||
|
if (*end_of_valid_d != '\0' || end_of_valid_d == value) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*doubleval = double_value;
|
||||||
|
return TRUE;
|
||||||
|
}
|
60
common/gdm-settings-utils.h
Normal file
60
common/gdm-settings-utils.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_SETTINGS_UTILS_H
|
||||||
|
#define __GDM_SETTINGS_UTILS_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GdmSettingsEntry GdmSettingsEntry;
|
||||||
|
|
||||||
|
GdmSettingsEntry * gdm_settings_entry_new (void);
|
||||||
|
void gdm_settings_entry_free (GdmSettingsEntry *entry);
|
||||||
|
|
||||||
|
const char * gdm_settings_entry_get_key (GdmSettingsEntry *entry);
|
||||||
|
const char * gdm_settings_entry_get_signature (GdmSettingsEntry *entry);
|
||||||
|
const char * gdm_settings_entry_get_default_value (GdmSettingsEntry *entry);
|
||||||
|
const char * gdm_settings_entry_get_value (GdmSettingsEntry *entry);
|
||||||
|
|
||||||
|
void gdm_settings_entry_set_value (GdmSettingsEntry *entry,
|
||||||
|
const char *value);
|
||||||
|
|
||||||
|
gboolean gdm_settings_parse_schemas (const char *file,
|
||||||
|
const char *root,
|
||||||
|
GSList **list);
|
||||||
|
|
||||||
|
gboolean gdm_settings_parse_value_as_boolean (const char *value,
|
||||||
|
gboolean *bool);
|
||||||
|
gboolean gdm_settings_parse_value_as_integer (const char *value,
|
||||||
|
int *intval);
|
||||||
|
gboolean gdm_settings_parse_value_as_double (const char *value,
|
||||||
|
gdouble *doubleval);
|
||||||
|
|
||||||
|
char * gdm_settings_parse_boolean_as_value (gboolean boolval);
|
||||||
|
char * gdm_settings_parse_integer_as_value (int intval);
|
||||||
|
char * gdm_settings_parse_double_as_value (gdouble doubleval);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_SETTINGS_UTILS_H */
|
257
common/gdm-settings.c
Normal file
257
common/gdm-settings.c
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gdm-settings.h"
|
||||||
|
|
||||||
|
#include "gdm-settings-desktop-backend.h"
|
||||||
|
|
||||||
|
struct _GdmSettings
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
GList *backends;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VALUE_CHANGED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
static void gdm_settings_class_init (GdmSettingsClass *klass);
|
||||||
|
static void gdm_settings_init (GdmSettings *settings);
|
||||||
|
static void gdm_settings_finalize (GObject *object);
|
||||||
|
|
||||||
|
static gpointer settings_object = NULL;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmSettings, gdm_settings, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gdm_settings_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark ret = 0;
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = g_quark_from_static_string ("gdm_settings_error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_get_value (GdmSettings *settings,
|
||||||
|
const char *key,
|
||||||
|
char **value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GError *local_error;
|
||||||
|
gboolean res;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
|
||||||
|
g_return_val_if_fail (settings->backends != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
|
||||||
|
for (l = settings->backends; l; l = g_list_next (l)) {
|
||||||
|
GdmSettingsBackend *backend = l->data;
|
||||||
|
|
||||||
|
if (local_error) {
|
||||||
|
g_error_free (local_error);
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = gdm_settings_backend_get_value (backend,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
&local_error);
|
||||||
|
if (res)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (! res) {
|
||||||
|
g_propagate_error (error, local_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_settings_set_value (GdmSettings *settings,
|
||||||
|
const char *key,
|
||||||
|
const char *value,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GError *local_error;
|
||||||
|
gboolean res;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
|
||||||
|
g_return_val_if_fail (settings->backends != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (key != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (value != NULL, FALSE);
|
||||||
|
|
||||||
|
g_debug ("Setting value %s", key);
|
||||||
|
|
||||||
|
local_error = NULL;
|
||||||
|
|
||||||
|
for (l = settings->backends; l; l = g_list_next (l)) {
|
||||||
|
GdmSettingsBackend *backend = l->data;
|
||||||
|
|
||||||
|
if (local_error) {
|
||||||
|
g_error_free (local_error);
|
||||||
|
local_error = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = gdm_settings_backend_set_value (backend,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
&local_error);
|
||||||
|
if (res)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! res) {
|
||||||
|
g_propagate_error (error, local_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_class_init (GdmSettingsClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_settings_finalize;
|
||||||
|
|
||||||
|
signals [VALUE_CHANGED] =
|
||||||
|
g_signal_new ("value-changed",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_generic,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
3,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_STRING,
|
||||||
|
G_TYPE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
backend_value_changed (GdmSettingsBackend *backend,
|
||||||
|
const char *key,
|
||||||
|
const char *old_value,
|
||||||
|
const char *new_value,
|
||||||
|
GdmSettings *settings)
|
||||||
|
{
|
||||||
|
g_debug ("Emitting value-changed %s %s %s", key, old_value, new_value);
|
||||||
|
|
||||||
|
/* proxy it to internal listeners */
|
||||||
|
g_signal_emit (settings, signals [VALUE_CHANGED], 0, key, old_value, new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_settings_reload (GdmSettings *settings)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
GdmSettingsBackend *backend;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_SETTINGS (settings));
|
||||||
|
|
||||||
|
g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL);
|
||||||
|
g_list_free (settings->backends);
|
||||||
|
settings->backends = NULL;
|
||||||
|
|
||||||
|
backend = gdm_settings_desktop_backend_new (GDM_CUSTOM_CONF);
|
||||||
|
if (backend)
|
||||||
|
settings->backends = g_list_prepend (NULL, backend);
|
||||||
|
|
||||||
|
backend = gdm_settings_desktop_backend_new (GDM_RUNTIME_CONF);
|
||||||
|
if (backend)
|
||||||
|
settings->backends = g_list_prepend (settings->backends, backend);
|
||||||
|
|
||||||
|
for (l = settings->backends; l; l = g_list_next (l)) {
|
||||||
|
backend = l->data;
|
||||||
|
|
||||||
|
g_signal_connect (backend,
|
||||||
|
"value-changed",
|
||||||
|
G_CALLBACK (backend_value_changed),
|
||||||
|
settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_init (GdmSettings *settings)
|
||||||
|
{
|
||||||
|
gdm_settings_reload (settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_settings_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmSettings *settings;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_SETTINGS (object));
|
||||||
|
|
||||||
|
settings = GDM_SETTINGS (object);
|
||||||
|
|
||||||
|
g_return_if_fail (settings != NULL);
|
||||||
|
|
||||||
|
g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL);
|
||||||
|
g_list_free (settings->backends);
|
||||||
|
settings->backends = NULL;
|
||||||
|
|
||||||
|
settings_object = NULL;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmSettings *
|
||||||
|
gdm_settings_new (void)
|
||||||
|
{
|
||||||
|
if (settings_object != NULL) {
|
||||||
|
g_object_ref (settings_object);
|
||||||
|
} else {
|
||||||
|
settings_object = g_object_new (GDM_TYPE_SETTINGS, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDM_SETTINGS (settings_object);
|
||||||
|
}
|
58
common/gdm-settings.h
Normal file
58
common/gdm-settings.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_SETTINGS_H
|
||||||
|
#define __GDM_SETTINGS_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SETTINGS (gdm_settings_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSettings, gdm_settings, GDM, SETTINGS, GObject)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_SETTINGS_ERROR_GENERAL,
|
||||||
|
GDM_SETTINGS_ERROR_KEY_NOT_FOUND
|
||||||
|
} GdmSettingsError;
|
||||||
|
|
||||||
|
#define GDM_SETTINGS_ERROR gdm_settings_error_quark ()
|
||||||
|
|
||||||
|
GQuark gdm_settings_error_quark (void);
|
||||||
|
|
||||||
|
GdmSettings * gdm_settings_new (void);
|
||||||
|
void gdm_settings_reload (GdmSettings *settings);
|
||||||
|
|
||||||
|
/* exported */
|
||||||
|
|
||||||
|
gboolean gdm_settings_get_value (GdmSettings *settings,
|
||||||
|
const char *key,
|
||||||
|
char **value,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_settings_set_value (GdmSettings *settings,
|
||||||
|
const char *key,
|
||||||
|
const char *value,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_SETTINGS_H */
|
43
common/meson.build
Normal file
43
common/meson.build
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
libgdmcommon_src = files(
|
||||||
|
'gdm-address.c',
|
||||||
|
'gdm-common.c',
|
||||||
|
'gdm-log.c',
|
||||||
|
'gdm-profile.c',
|
||||||
|
'gdm-settings-backend.c',
|
||||||
|
'gdm-settings-desktop-backend.c',
|
||||||
|
'gdm-settings-direct.c',
|
||||||
|
'gdm-settings-utils.c',
|
||||||
|
'gdm-settings.c',
|
||||||
|
)
|
||||||
|
|
||||||
|
libgdmcommon_deps = [
|
||||||
|
logind_dep,
|
||||||
|
gobject_dep,
|
||||||
|
gio_dep,
|
||||||
|
gio_unix_dep,
|
||||||
|
]
|
||||||
|
|
||||||
|
if libselinux_dep.found()
|
||||||
|
libgdmcommon_deps += libselinux_dep
|
||||||
|
endif
|
||||||
|
|
||||||
|
libgdmcommon_lib = static_library('gdmcommon',
|
||||||
|
libgdmcommon_src,
|
||||||
|
dependencies: libgdmcommon_deps,
|
||||||
|
include_directories: config_h_dir,
|
||||||
|
)
|
||||||
|
|
||||||
|
libgdmcommon_dep = declare_dependency(
|
||||||
|
link_with: libgdmcommon_lib,
|
||||||
|
dependencies: libgdmcommon_deps,
|
||||||
|
include_directories: include_directories('.'),
|
||||||
|
)
|
||||||
|
|
||||||
|
install_data('gdb-cmd')
|
||||||
|
|
||||||
|
# test-log exectuable
|
||||||
|
test_log = executable('test-log',
|
||||||
|
'test-log.c',
|
||||||
|
dependencies: libgdmcommon_dep,
|
||||||
|
include_directories: config_h_dir,
|
||||||
|
)
|
60
common/test-log.c
Normal file
60
common/test-log.c
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
#include "gdm-log.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_log (void)
|
||||||
|
{
|
||||||
|
gdm_log_init ();
|
||||||
|
|
||||||
|
g_debug ("Test debug 1");
|
||||||
|
gdm_log_set_debug (TRUE);
|
||||||
|
g_debug ("Test debug 2");
|
||||||
|
|
||||||
|
g_message ("Test message");
|
||||||
|
g_warning ("Test warning");
|
||||||
|
g_critical ("Test critical");
|
||||||
|
g_error ("Test error");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
test_log ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
202
daemon/gdm-dbus-util.c
Normal file
202
daemon/gdm-dbus-util.c
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gdm-dbus-util.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <gio/gunixsocketaddress.h>
|
||||||
|
|
||||||
|
/* a subset of org.freedesktop.DBus interface, to be used by internal servers */
|
||||||
|
static const char *dbus_introspection =
|
||||||
|
"<node name=\"/org/freedesktop/DBus\">"
|
||||||
|
" <interface name=\"org.freedesktop.DBus\">"
|
||||||
|
" <method name=\"AddMatch\">"
|
||||||
|
" <arg name=\"match_rule\" type=\"s\" direction=\"in\" />"
|
||||||
|
" </method>"
|
||||||
|
" </interface>"
|
||||||
|
"</node>";
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_bus_method (GDBusConnection *connection,
|
||||||
|
const char *sender,
|
||||||
|
const char *object_path,
|
||||||
|
const char *interface_name,
|
||||||
|
const char *method_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_connection (GDBusServer *server,
|
||||||
|
GDBusConnection *new_connection,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr(GDBusNodeInfo) bus_info = NULL;
|
||||||
|
GDBusInterfaceVTable bus_vtable = { handle_bus_method };
|
||||||
|
|
||||||
|
bus_info = g_dbus_node_info_new_for_xml (dbus_introspection,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_debug ("GdmDBusServer: new connection %p", new_connection);
|
||||||
|
|
||||||
|
g_dbus_connection_register_object (new_connection,
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
bus_info->interfaces[0],
|
||||||
|
&bus_vtable,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/* We're not handling the signal */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDBusServer *
|
||||||
|
gdm_dbus_setup_private_server (GDBusAuthObserver *observer,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autofree char *guid = NULL;
|
||||||
|
const char *client_address;
|
||||||
|
g_autoptr(GDBusServer) server = NULL;
|
||||||
|
|
||||||
|
/* Ensure the private bus directory exists */
|
||||||
|
if (g_mkdir_with_parents (GDM_PRIVATE_DBUS_DIR, 0711) == -1) {
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), g_strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (g_chmod (GDM_PRIVATE_DBUS_DIR, 0711) == -1) {
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno), g_strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
guid = g_dbus_generate_guid ();
|
||||||
|
|
||||||
|
server = g_dbus_server_new_sync ("unix:dir=" GDM_PRIVATE_DBUS_DIR,
|
||||||
|
G_DBUS_SERVER_FLAGS_NONE,
|
||||||
|
guid,
|
||||||
|
observer,
|
||||||
|
NULL,
|
||||||
|
error);
|
||||||
|
|
||||||
|
client_address = g_dbus_server_get_client_address (server);
|
||||||
|
|
||||||
|
if (g_str_has_prefix (client_address, "unix:path=")) {
|
||||||
|
client_address += strlen("unix:path=");
|
||||||
|
g_chmod (client_address, 0666);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (server, "new-connection",
|
||||||
|
G_CALLBACK (handle_connection),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return g_steal_pointer (&server);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_dbus_get_pid_for_name (const char *system_bus_name,
|
||||||
|
pid_t *out_pid,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GDBusConnection) bus = NULL;
|
||||||
|
g_autoptr(GVariant) reply = NULL;
|
||||||
|
unsigned int v;
|
||||||
|
|
||||||
|
g_return_val_if_fail (system_bus_name != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (out_pid != NULL, FALSE);
|
||||||
|
|
||||||
|
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
|
||||||
|
if (bus == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (bus,
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"GetConnectionUnixProcessID",
|
||||||
|
g_variant_new ("(s)", system_bus_name),
|
||||||
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
NULL, error);
|
||||||
|
if (reply == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (reply, "(u)", &v);
|
||||||
|
*out_pid = v;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_dbus_get_uid_for_name (const char *system_bus_name,
|
||||||
|
uid_t *out_uid,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GDBusConnection) bus = NULL;
|
||||||
|
g_autoptr(GVariant) reply = NULL;
|
||||||
|
unsigned int v;
|
||||||
|
|
||||||
|
g_return_val_if_fail (system_bus_name != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (out_uid != NULL, FALSE);
|
||||||
|
|
||||||
|
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
|
||||||
|
if (bus == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (bus,
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"GetConnectionUnixUser",
|
||||||
|
g_variant_new ("(s)", system_bus_name),
|
||||||
|
G_VARIANT_TYPE ("(u)"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
NULL, error);
|
||||||
|
if (reply == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (reply, "(u)", &v);
|
||||||
|
*out_uid = v;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_dbus_error_ensure (GQuark domain)
|
||||||
|
{
|
||||||
|
/* The primary purpose of this function is to make sure the error quark
|
||||||
|
* is registered internally with gdbus before any bus traffic occurs,
|
||||||
|
* so we get remote errors mapped correctly to their local counterparts.
|
||||||
|
* This error quark registration happens implicitly the first time the
|
||||||
|
* quark is used.
|
||||||
|
* Note that g_debug is never optimized away, only the output is suppressed.
|
||||||
|
*/
|
||||||
|
g_debug ("GdmDBusUtils: Registered DBus error domain '%s'",
|
||||||
|
g_quark_to_string (domain));
|
||||||
|
}
|
40
daemon/gdm-dbus-util.h
Normal file
40
daemon/gdm-dbus-util.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_DBUS_UTIL_H
|
||||||
|
#define __GDM_DBUS_UTIL_H
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
GDBusServer *gdm_dbus_setup_private_server (GDBusAuthObserver *observer,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gdm_dbus_get_pid_for_name (const char *system_bus_name,
|
||||||
|
pid_t *out_pid,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gdm_dbus_get_uid_for_name (const char *system_bus_name,
|
||||||
|
uid_t *out_uid,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gdm_dbus_error_ensure (GQuark domain);
|
||||||
|
#endif
|
604
daemon/gdm-display-access-file.c
Normal file
604
daemon/gdm-display-access-file.c
Normal file
|
@ -0,0 +1,604 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* gdm-display-access-file.c - Abstraction around xauth cookies
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Ray Strode <rstrode@redhat.com>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_X11_SUPPORT
|
||||||
|
#include <X11/Xauth.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gdm-display-access-file.h"
|
||||||
|
#include "gdm-common.h"
|
||||||
|
|
||||||
|
struct _GdmDisplayAccessFile
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
char *username;
|
||||||
|
FILE *fp;
|
||||||
|
char *path;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef GDM_DISPLAY_ACCESS_COOKIE_SIZE
|
||||||
|
#define GDM_DISPLAY_ACCESS_COOKIE_SIZE 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
#define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void gdm_display_access_file_finalize (GObject * object);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0 = 0,
|
||||||
|
PROP_USERNAME,
|
||||||
|
PROP_PATH
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmDisplayAccessFile, gdm_display_access_file, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_access_file_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmDisplayAccessFile *access_file;
|
||||||
|
|
||||||
|
access_file = GDM_DISPLAY_ACCESS_FILE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_USERNAME:
|
||||||
|
g_value_set_string (value, access_file->username);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_PATH:
|
||||||
|
g_value_set_string (value, access_file->path);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_access_file_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmDisplayAccessFile *access_file;
|
||||||
|
|
||||||
|
access_file = GDM_DISPLAY_ACCESS_FILE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_USERNAME:
|
||||||
|
g_assert (access_file->username == NULL);
|
||||||
|
access_file->username = g_value_dup_string (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_access_file_class_init (GdmDisplayAccessFileClass *access_file_class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
GParamSpec *param_spec;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (access_file_class);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_display_access_file_finalize;
|
||||||
|
object_class->get_property = gdm_display_access_file_get_property;
|
||||||
|
object_class->set_property = gdm_display_access_file_set_property;
|
||||||
|
|
||||||
|
param_spec = g_param_spec_string ("username",
|
||||||
|
"Username",
|
||||||
|
"Owner of Xauthority file",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (object_class, PROP_USERNAME, param_spec);
|
||||||
|
param_spec = g_param_spec_string ("path",
|
||||||
|
"Path",
|
||||||
|
"Path to Xauthority file",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READABLE);
|
||||||
|
g_object_class_install_property (object_class, PROP_PATH, param_spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_access_file_init (GdmDisplayAccessFile *access_file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_access_file_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmDisplayAccessFile *file;
|
||||||
|
GObjectClass *parent_class;
|
||||||
|
|
||||||
|
file = GDM_DISPLAY_ACCESS_FILE (object);
|
||||||
|
parent_class = G_OBJECT_CLASS (gdm_display_access_file_parent_class);
|
||||||
|
|
||||||
|
if (file->fp != NULL) {
|
||||||
|
gdm_display_access_file_close (file);
|
||||||
|
}
|
||||||
|
g_assert (file->path == NULL);
|
||||||
|
|
||||||
|
if (file->username != NULL) {
|
||||||
|
g_free (file->username);
|
||||||
|
file->username = NULL;
|
||||||
|
g_object_notify (object, "username");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_class->finalize != NULL) {
|
||||||
|
parent_class->finalize (object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gdm_display_access_file_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark error_quark = 0;
|
||||||
|
|
||||||
|
if (error_quark == 0) {
|
||||||
|
error_quark = g_quark_from_static_string ("gdm-display-access-file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return error_quark;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplayAccessFile *
|
||||||
|
gdm_display_access_file_new (const char *username)
|
||||||
|
{
|
||||||
|
GdmDisplayAccessFile *access_file;
|
||||||
|
g_return_val_if_fail (username != NULL, NULL);
|
||||||
|
|
||||||
|
access_file = g_object_new (GDM_TYPE_DISPLAY_ACCESS_FILE,
|
||||||
|
"username", username,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return access_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_get_uid_and_gid_for_user (const char *username,
|
||||||
|
uid_t *uid,
|
||||||
|
gid_t *gid)
|
||||||
|
{
|
||||||
|
struct passwd *passwd_entry;
|
||||||
|
|
||||||
|
g_assert (username != NULL);
|
||||||
|
g_assert (uid != NULL);
|
||||||
|
g_assert (gid != NULL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
gdm_get_pwent_for_name (username, &passwd_entry);
|
||||||
|
|
||||||
|
if (passwd_entry == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*uid = passwd_entry->pw_uid;
|
||||||
|
*gid = passwd_entry->pw_gid;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clean_up_stale_auth_subdirs (void)
|
||||||
|
{
|
||||||
|
g_autoptr(GDir) dir = NULL;
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
dir = g_dir_open (GDM_XAUTH_DIR, 0, NULL);
|
||||||
|
|
||||||
|
if (dir == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((filename = g_dir_read_name (dir)) != NULL) {
|
||||||
|
g_autofree char *path = NULL;
|
||||||
|
|
||||||
|
path = g_build_filename (GDM_XAUTH_DIR, filename, NULL);
|
||||||
|
|
||||||
|
/* Will only succeed if the directory is empty
|
||||||
|
*/
|
||||||
|
g_rmdir (path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE *
|
||||||
|
_create_xauth_file_for_user (const char *username,
|
||||||
|
char **filename,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autofree char *template = NULL;
|
||||||
|
g_autofree char *auth_filename = NULL;
|
||||||
|
const char *dir_name;
|
||||||
|
int fd;
|
||||||
|
FILE *fp;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
|
||||||
|
g_assert (filename != NULL);
|
||||||
|
|
||||||
|
*filename = NULL;
|
||||||
|
|
||||||
|
/* Create directory if not exist, then set permission 0711 and ownership root:gdm */
|
||||||
|
if (g_file_test (GDM_XAUTH_DIR, G_FILE_TEST_IS_DIR) == FALSE) {
|
||||||
|
g_remove (GDM_XAUTH_DIR);
|
||||||
|
if (g_mkdir (GDM_XAUTH_DIR, 0711) != 0) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
g_file_error_from_errno (errno),
|
||||||
|
g_strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_chmod (GDM_XAUTH_DIR, 0711);
|
||||||
|
if (!_get_uid_and_gid_for_user (GDM_USERNAME, &uid, &gid)) {
|
||||||
|
g_set_error (error,
|
||||||
|
GDM_DISPLAY_ERROR,
|
||||||
|
GDM_DISPLAY_ERROR_GETTING_USER_INFO,
|
||||||
|
_("Could not find user “%s” on system"),
|
||||||
|
GDM_USERNAME);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chown (GDM_XAUTH_DIR, 0, gid) != 0) {
|
||||||
|
g_warning ("Unable to change owner of '%s'",
|
||||||
|
GDM_XAUTH_DIR);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* if it does exist make sure it has correct mode 0711 */
|
||||||
|
g_chmod (GDM_XAUTH_DIR, 0711);
|
||||||
|
|
||||||
|
/* and clean up any stale auth subdirs */
|
||||||
|
clean_up_stale_auth_subdirs ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_get_uid_and_gid_for_user (username, &uid, &gid)) {
|
||||||
|
g_set_error (error,
|
||||||
|
GDM_DISPLAY_ERROR,
|
||||||
|
GDM_DISPLAY_ERROR_GETTING_USER_INFO,
|
||||||
|
_("Could not find user “%s” on system"),
|
||||||
|
username);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template = g_strdup_printf (GDM_XAUTH_DIR
|
||||||
|
"/auth-for-%s-XXXXXX",
|
||||||
|
username);
|
||||||
|
|
||||||
|
g_debug ("GdmDisplayAccessFile: creating xauth directory %s", template);
|
||||||
|
/* Initially create with mode 01700 then later chmod after we create database */
|
||||||
|
errno = 0;
|
||||||
|
dir_name = g_mkdtemp (template);
|
||||||
|
if (dir_name == NULL) {
|
||||||
|
g_set_error (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
g_file_error_from_errno (errno),
|
||||||
|
"Unable to create temp dir from tempalte '%s': %s",
|
||||||
|
template,
|
||||||
|
g_strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GdmDisplayAccessFile: chowning %s to %u:%u",
|
||||||
|
dir_name, (guint)uid, (guint)gid);
|
||||||
|
errno = 0;
|
||||||
|
if (chown (dir_name, uid, gid) < 0) {
|
||||||
|
g_set_error (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
g_file_error_from_errno (errno),
|
||||||
|
"Unable to change permission of '%s': %s",
|
||||||
|
dir_name,
|
||||||
|
g_strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
auth_filename = g_build_filename (dir_name, "database", NULL);
|
||||||
|
|
||||||
|
g_debug ("GdmDisplayAccessFile: creating %s", auth_filename);
|
||||||
|
/* mode 00600 */
|
||||||
|
errno = 0;
|
||||||
|
fd = g_open (auth_filename,
|
||||||
|
O_RDWR | O_CREAT | O_EXCL | O_BINARY,
|
||||||
|
S_IRUSR | S_IWUSR);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
g_set_error (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
g_file_error_from_errno (errno),
|
||||||
|
"Unable to open '%s': %s",
|
||||||
|
auth_filename,
|
||||||
|
g_strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GdmDisplayAccessFile: chowning %s to %u:%u", auth_filename, (guint)uid, (guint)gid);
|
||||||
|
errno = 0;
|
||||||
|
if (fchown (fd, uid, gid) < 0) {
|
||||||
|
g_set_error (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
g_file_error_from_errno (errno),
|
||||||
|
"Unable to change owner for '%s': %s",
|
||||||
|
auth_filename,
|
||||||
|
g_strerror (errno));
|
||||||
|
close (fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now open up permissions on per-session directory */
|
||||||
|
g_debug ("GdmDisplayAccessFile: chmoding %s to 0711", dir_name);
|
||||||
|
g_chmod (dir_name, 0711);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
fp = fdopen (fd, "w");
|
||||||
|
if (fp == NULL) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
g_file_error_from_errno (errno),
|
||||||
|
g_strerror (errno));
|
||||||
|
close (fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*filename = g_steal_pointer (&auth_filename);
|
||||||
|
|
||||||
|
/* don't close fd on purpose */
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_display_access_file_open (GdmDisplayAccessFile *file,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) create_error = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_ACCESS_FILE (file), FALSE);
|
||||||
|
g_return_val_if_fail (file->fp == NULL, FALSE);
|
||||||
|
g_return_val_if_fail (file->path == NULL, FALSE);
|
||||||
|
|
||||||
|
file->fp = _create_xauth_file_for_user (file->username,
|
||||||
|
&file->path,
|
||||||
|
&create_error);
|
||||||
|
|
||||||
|
if (file->fp == NULL) {
|
||||||
|
g_propagate_error (error, g_steal_pointer (&create_error));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_X11_SUPPORT
|
||||||
|
static void
|
||||||
|
_get_auth_info_for_display (GdmDisplayAccessFile *file,
|
||||||
|
GdmDisplay *display,
|
||||||
|
unsigned short *family,
|
||||||
|
unsigned short *address_length,
|
||||||
|
char **address,
|
||||||
|
unsigned short *number_length,
|
||||||
|
char **number,
|
||||||
|
unsigned short *name_length,
|
||||||
|
char **name)
|
||||||
|
{
|
||||||
|
int display_number;
|
||||||
|
gboolean is_local;
|
||||||
|
|
||||||
|
gdm_display_is_local (display, &is_local, NULL);
|
||||||
|
|
||||||
|
if (is_local) {
|
||||||
|
/* We could just use FamilyWild here except xauth
|
||||||
|
* (and by extension su and ssh) doesn't support it yet
|
||||||
|
*
|
||||||
|
* https://bugs.freedesktop.org/show_bug.cgi?id=43425
|
||||||
|
*/
|
||||||
|
char localhost[_POSIX_HOST_NAME_MAX + 1] = "";
|
||||||
|
*family = FamilyLocal;
|
||||||
|
if (gethostname (localhost, _POSIX_HOST_NAME_MAX) == 0) {
|
||||||
|
*address = g_strdup (localhost);
|
||||||
|
} else {
|
||||||
|
*address = g_strdup ("localhost");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*family = FamilyWild;
|
||||||
|
gdm_display_get_remote_hostname (display, address, NULL);
|
||||||
|
}
|
||||||
|
*address_length = strlen (*address);
|
||||||
|
|
||||||
|
gdm_display_get_x11_display_number (display, &display_number, NULL);
|
||||||
|
*number = g_strdup_printf ("%d", display_number);
|
||||||
|
*number_length = strlen (*number);
|
||||||
|
|
||||||
|
*name = g_strdup ("MIT-MAGIC-COOKIE-1");
|
||||||
|
*name_length = strlen (*name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_display_access_file_add_display (GdmDisplayAccessFile *file,
|
||||||
|
GdmDisplay *display,
|
||||||
|
char **cookie,
|
||||||
|
gsize *cookie_size,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) add_error = NULL;
|
||||||
|
gboolean display_added;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_ACCESS_FILE (file), FALSE);
|
||||||
|
g_return_val_if_fail (file->path != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (display != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (cookie != NULL, FALSE);
|
||||||
|
|
||||||
|
*cookie = gdm_generate_random_bytes (GDM_DISPLAY_ACCESS_COOKIE_SIZE,
|
||||||
|
&add_error);
|
||||||
|
|
||||||
|
if (*cookie == NULL) {
|
||||||
|
g_propagate_error (error, g_steal_pointer (&add_error));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cookie_size = GDM_DISPLAY_ACCESS_COOKIE_SIZE;
|
||||||
|
|
||||||
|
display_added = gdm_display_access_file_add_display_with_cookie (file, display,
|
||||||
|
*cookie,
|
||||||
|
*cookie_size,
|
||||||
|
&add_error);
|
||||||
|
if (!display_added) {
|
||||||
|
g_free (*cookie);
|
||||||
|
*cookie = NULL;
|
||||||
|
g_propagate_error (error, g_steal_pointer (&add_error));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_display_access_file_add_display_with_cookie (GdmDisplayAccessFile *file,
|
||||||
|
GdmDisplay *display,
|
||||||
|
const char *cookie,
|
||||||
|
gsize cookie_size,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_X11_SUPPORT
|
||||||
|
Xauth auth_entry;
|
||||||
|
gboolean display_added;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_ACCESS_FILE (file), FALSE);
|
||||||
|
g_return_val_if_fail (file->path != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (display != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (cookie != NULL, FALSE);
|
||||||
|
|
||||||
|
_get_auth_info_for_display (file, display,
|
||||||
|
&auth_entry.family,
|
||||||
|
&auth_entry.address_length,
|
||||||
|
&auth_entry.address,
|
||||||
|
&auth_entry.number_length,
|
||||||
|
&auth_entry.number,
|
||||||
|
&auth_entry.name_length,
|
||||||
|
&auth_entry.name);
|
||||||
|
|
||||||
|
auth_entry.data = (char *) cookie;
|
||||||
|
auth_entry.data_length = cookie_size;
|
||||||
|
|
||||||
|
/* FIXME: We should lock the file in case the X server is
|
||||||
|
* trying to use it, too.
|
||||||
|
*/
|
||||||
|
if (!XauWriteAuth (file->fp, &auth_entry)
|
||||||
|
|| fflush (file->fp) == EOF) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
G_FILE_ERROR,
|
||||||
|
g_file_error_from_errno (errno),
|
||||||
|
g_strerror (errno));
|
||||||
|
display_added = FALSE;
|
||||||
|
} else {
|
||||||
|
display_added = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we wrote a FamilyLocal entry, we still want a FamilyWild
|
||||||
|
* entry, because it's more resiliant against hostname changes
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
if (auth_entry.family == FamilyLocal) {
|
||||||
|
auth_entry.family = FamilyWild;
|
||||||
|
|
||||||
|
if (XauWriteAuth (file->fp, &auth_entry)
|
||||||
|
&& fflush (file->fp) != EOF) {
|
||||||
|
display_added = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (auth_entry.address);
|
||||||
|
g_free (auth_entry.number);
|
||||||
|
g_free (auth_entry.name);
|
||||||
|
|
||||||
|
return display_added;
|
||||||
|
#else
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_display_access_file_close (GdmDisplayAccessFile *file)
|
||||||
|
{
|
||||||
|
g_autofree char *auth_dir = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_DISPLAY_ACCESS_FILE (file));
|
||||||
|
g_return_if_fail (file->fp != NULL);
|
||||||
|
g_return_if_fail (file->path != NULL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if (g_unlink (file->path) != 0) {
|
||||||
|
g_warning ("GdmDisplayAccessFile: Unable to remove X11 authority database '%s': %s",
|
||||||
|
file->path,
|
||||||
|
g_strerror (errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* still try to remove dir even if file remove failed,
|
||||||
|
may have already been removed by someone else */
|
||||||
|
/* we own the parent directory too */
|
||||||
|
auth_dir = g_path_get_dirname (file->path);
|
||||||
|
if (auth_dir != NULL) {
|
||||||
|
errno = 0;
|
||||||
|
if (g_rmdir (auth_dir) != 0) {
|
||||||
|
g_warning ("GdmDisplayAccessFile: Unable to remove X11 authority directory '%s': %s",
|
||||||
|
auth_dir,
|
||||||
|
g_strerror (errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (file->path);
|
||||||
|
file->path = NULL;
|
||||||
|
g_object_notify (G_OBJECT (file), "path");
|
||||||
|
|
||||||
|
fclose (file->fp);
|
||||||
|
file->fp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_display_access_file_get_path (GdmDisplayAccessFile *file)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_ACCESS_FILE (file), NULL);
|
||||||
|
|
||||||
|
return g_strdup (file->path);
|
||||||
|
}
|
67
daemon/gdm-display-access-file.h
Normal file
67
daemon/gdm-display-access-file.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* gdm-display-access-file.h - Abstraction around xauth cookies
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Ray Strode <rstrode@redhat.com>
|
||||||
|
*
|
||||||
|
* Written by Ray Strode <rstrode@redhat.com>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
#ifndef __GDM_DISPLAY_ACCESS_FILE_H__
|
||||||
|
#define __GDM_DISPLAY_ACCESS_FILE_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_DISPLAY_ACCESS_FILE (gdm_display_access_file_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmDisplayAccessFile, gdm_display_access_file, GDM, DISPLAY_ACCESS_FILE, GObject)
|
||||||
|
|
||||||
|
#define GDM_DISPLAY_ACCESS_FILE_ERROR (gdm_display_access_file_error_quark ())
|
||||||
|
|
||||||
|
typedef enum _GdmDisplayAccessFileError GdmDisplayAccessFileError;
|
||||||
|
|
||||||
|
enum _GdmDisplayAccessFileError
|
||||||
|
{
|
||||||
|
GDM_DISPLAY_ACCESS_FILE_ERROR_GENERAL = 0,
|
||||||
|
GDM_DISPLAY_ACCESS_FILE_ERROR_FINDING_AUTH_ENTRY
|
||||||
|
};
|
||||||
|
|
||||||
|
GQuark gdm_display_access_file_error_quark (void);
|
||||||
|
|
||||||
|
GdmDisplayAccessFile *gdm_display_access_file_new (const char *username);
|
||||||
|
gboolean gdm_display_access_file_open (GdmDisplayAccessFile *file,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_access_file_add_display (GdmDisplayAccessFile *file,
|
||||||
|
GdmDisplay *display,
|
||||||
|
char **cookie,
|
||||||
|
gsize *cookie_size,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_access_file_add_display_with_cookie (GdmDisplayAccessFile *file,
|
||||||
|
GdmDisplay *display,
|
||||||
|
const char *cookie,
|
||||||
|
gsize cookie_size,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void gdm_display_access_file_close (GdmDisplayAccessFile *file);
|
||||||
|
char *gdm_display_access_file_get_path (GdmDisplayAccessFile *file);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* __GDM_DISPLAY_ACCESS_FILE_H__ */
|
241
daemon/gdm-display-factory.c
Normal file
241
daemon/gdm-display-factory.c
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display-factory.h"
|
||||||
|
#include "gdm-display-store.h"
|
||||||
|
|
||||||
|
typedef struct _GdmDisplayFactoryPrivate
|
||||||
|
{
|
||||||
|
GdmDisplayStore *display_store;
|
||||||
|
guint purge_displays_id;
|
||||||
|
} GdmDisplayFactoryPrivate;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_DISPLAY_STORE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_display_factory_class_init (GdmDisplayFactoryClass *klass);
|
||||||
|
static void gdm_display_factory_init (GdmDisplayFactory *factory);
|
||||||
|
static void gdm_display_factory_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdmDisplayFactory, gdm_display_factory, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gdm_display_factory_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark ret = 0;
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = g_quark_from_static_string ("gdm_display_factory_error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
purge_display (char *id,
|
||||||
|
GdmDisplay *display,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = gdm_display_get_status (display);
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case GDM_DISPLAY_FINISHED:
|
||||||
|
case GDM_DISPLAY_FAILED:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
purge_displays (GdmDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
GdmDisplayFactoryPrivate *priv;
|
||||||
|
|
||||||
|
priv = gdm_display_factory_get_instance_private (factory);
|
||||||
|
priv->purge_displays_id = 0;
|
||||||
|
gdm_display_store_foreach_remove (priv->display_store,
|
||||||
|
(GdmDisplayStoreFunc)purge_display,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_display_factory_queue_purge_displays (GdmDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
GdmDisplayFactoryPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_DISPLAY_FACTORY (factory));
|
||||||
|
|
||||||
|
priv = gdm_display_factory_get_instance_private (factory);
|
||||||
|
if (priv->purge_displays_id == 0) {
|
||||||
|
priv->purge_displays_id = g_idle_add ((GSourceFunc) purge_displays, factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplayStore *
|
||||||
|
gdm_display_factory_get_display_store (GdmDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
GdmDisplayFactoryPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), NULL);
|
||||||
|
|
||||||
|
priv = gdm_display_factory_get_instance_private (factory);
|
||||||
|
return priv->display_store;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_display_factory_start (GdmDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
|
||||||
|
|
||||||
|
g_object_ref (factory);
|
||||||
|
ret = GDM_DISPLAY_FACTORY_GET_CLASS (factory)->start (factory);
|
||||||
|
g_object_unref (factory);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_display_factory_stop (GdmDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
|
||||||
|
|
||||||
|
g_object_ref (factory);
|
||||||
|
ret = GDM_DISPLAY_FACTORY_GET_CLASS (factory)->stop (factory);
|
||||||
|
g_object_unref (factory);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_factory_set_display_store (GdmDisplayFactory *factory,
|
||||||
|
GdmDisplayStore *display_store)
|
||||||
|
{
|
||||||
|
GdmDisplayFactoryPrivate *priv;
|
||||||
|
|
||||||
|
priv = gdm_display_factory_get_instance_private (factory);
|
||||||
|
g_clear_object (&priv->display_store);
|
||||||
|
|
||||||
|
if (display_store != NULL) {
|
||||||
|
priv->display_store = g_object_ref (display_store);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_factory_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmDisplayFactory *self;
|
||||||
|
|
||||||
|
self = GDM_DISPLAY_FACTORY (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_DISPLAY_STORE:
|
||||||
|
gdm_display_factory_set_display_store (self, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_factory_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmDisplayFactory *self;
|
||||||
|
GdmDisplayFactoryPrivate *priv;
|
||||||
|
|
||||||
|
self = GDM_DISPLAY_FACTORY (object);
|
||||||
|
priv = gdm_display_factory_get_instance_private (self);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_DISPLAY_STORE:
|
||||||
|
g_value_set_object (value, priv->display_store);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_factory_class_init (GdmDisplayFactoryClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_display_factory_get_property;
|
||||||
|
object_class->set_property = gdm_display_factory_set_property;
|
||||||
|
object_class->finalize = gdm_display_factory_finalize;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_DISPLAY_STORE,
|
||||||
|
g_param_spec_object ("display-store",
|
||||||
|
"display store",
|
||||||
|
"display store",
|
||||||
|
GDM_TYPE_DISPLAY_STORE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_factory_init (GdmDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_factory_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmDisplayFactory *factory;
|
||||||
|
GdmDisplayFactoryPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_DISPLAY_FACTORY (object));
|
||||||
|
|
||||||
|
factory = GDM_DISPLAY_FACTORY (object);
|
||||||
|
priv = gdm_display_factory_get_instance_private (factory);
|
||||||
|
|
||||||
|
g_return_if_fail (priv != NULL);
|
||||||
|
|
||||||
|
g_clear_handle_id (&priv->purge_displays_id, g_source_remove);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_display_factory_parent_class)->finalize (object);
|
||||||
|
}
|
59
daemon/gdm-display-factory.h
Normal file
59
daemon/gdm-display-factory.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_DISPLAY_FACTORY_H
|
||||||
|
#define __GDM_DISPLAY_FACTORY_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display-store.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_DISPLAY_FACTORY (gdm_display_factory_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GdmDisplayFactory, gdm_display_factory, GDM, DISPLAY_FACTORY, GObject)
|
||||||
|
|
||||||
|
struct _GdmDisplayFactoryClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
gboolean (*start) (GdmDisplayFactory *factory);
|
||||||
|
gboolean (*stop) (GdmDisplayFactory *factory);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_DISPLAY_FACTORY_ERROR_GENERAL
|
||||||
|
} GdmDisplayFactoryError;
|
||||||
|
|
||||||
|
#define GDM_DISPLAY_FACTORY_ERROR gdm_display_factory_error_quark ()
|
||||||
|
|
||||||
|
GQuark gdm_display_factory_error_quark (void);
|
||||||
|
GType gdm_display_factory_get_type (void);
|
||||||
|
|
||||||
|
gboolean gdm_display_factory_start (GdmDisplayFactory *manager);
|
||||||
|
gboolean gdm_display_factory_stop (GdmDisplayFactory *manager);
|
||||||
|
GdmDisplayStore * gdm_display_factory_get_display_store (GdmDisplayFactory *manager);
|
||||||
|
void gdm_display_factory_queue_purge_displays (GdmDisplayFactory *manager);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_DISPLAY_FACTORY_H */
|
327
daemon/gdm-display-store.c
Normal file
327
daemon/gdm-display-store.c
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display-store.h"
|
||||||
|
#include "gdm-display.h"
|
||||||
|
|
||||||
|
struct _GdmDisplayStore
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
GHashTable *displays;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GdmDisplayStore *store;
|
||||||
|
GdmDisplay *display;
|
||||||
|
} StoredDisplay;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DISPLAY_ADDED,
|
||||||
|
DISPLAY_REMOVED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
static void gdm_display_store_class_init (GdmDisplayStoreClass *klass);
|
||||||
|
static void gdm_display_store_init (GdmDisplayStore *display_store);
|
||||||
|
static void gdm_display_store_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmDisplayStore, gdm_display_store, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static StoredDisplay *
|
||||||
|
stored_display_new (GdmDisplayStore *store,
|
||||||
|
GdmDisplay *display)
|
||||||
|
{
|
||||||
|
StoredDisplay *stored_display;
|
||||||
|
|
||||||
|
stored_display = g_slice_new (StoredDisplay);
|
||||||
|
stored_display->store = store;
|
||||||
|
stored_display->display = g_object_ref (display);
|
||||||
|
|
||||||
|
return stored_display;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stored_display_free (StoredDisplay *stored_display)
|
||||||
|
{
|
||||||
|
g_signal_emit (G_OBJECT (stored_display->store),
|
||||||
|
signals[DISPLAY_REMOVED],
|
||||||
|
0,
|
||||||
|
stored_display->display);
|
||||||
|
|
||||||
|
g_debug ("GdmDisplayStore: Unreffing display: %p",
|
||||||
|
stored_display->display);
|
||||||
|
g_object_unref (stored_display->display);
|
||||||
|
|
||||||
|
g_slice_free (StoredDisplay, stored_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gdm_display_store_error_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark ret = 0;
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = g_quark_from_static_string ("gdm_display_store_error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_display_store_clear (GdmDisplayStore *store)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_DISPLAY_STORE (store));
|
||||||
|
g_debug ("GdmDisplayStore: Clearing display store");
|
||||||
|
g_hash_table_remove_all (store->displays);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
remove_display (char *id,
|
||||||
|
GdmDisplay *display,
|
||||||
|
GdmDisplay *display_to_remove)
|
||||||
|
{
|
||||||
|
if (display == display_to_remove) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_display_store_remove (GdmDisplayStore *store,
|
||||||
|
GdmDisplay *display)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), FALSE);
|
||||||
|
g_return_val_if_fail (display != NULL, FALSE);
|
||||||
|
|
||||||
|
gdm_display_store_foreach_remove (store,
|
||||||
|
(GdmDisplayStoreFunc)remove_display,
|
||||||
|
display);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GdmDisplayStoreFunc predicate;
|
||||||
|
gpointer user_data;
|
||||||
|
} FindClosure;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
find_func (const char *id,
|
||||||
|
StoredDisplay *stored_display,
|
||||||
|
FindClosure *closure)
|
||||||
|
{
|
||||||
|
return closure->predicate (id,
|
||||||
|
stored_display->display,
|
||||||
|
closure->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
foreach_func (const char *id,
|
||||||
|
StoredDisplay *stored_display,
|
||||||
|
FindClosure *closure)
|
||||||
|
{
|
||||||
|
(void) closure->predicate (id,
|
||||||
|
stored_display->display,
|
||||||
|
closure->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_display_store_foreach (GdmDisplayStore *store,
|
||||||
|
GdmDisplayStoreFunc func,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
FindClosure closure;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_DISPLAY_STORE (store));
|
||||||
|
g_return_if_fail (func != NULL);
|
||||||
|
|
||||||
|
closure.predicate = func;
|
||||||
|
closure.user_data = user_data;
|
||||||
|
|
||||||
|
g_hash_table_foreach (store->displays,
|
||||||
|
(GHFunc) foreach_func,
|
||||||
|
&closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplay *
|
||||||
|
gdm_display_store_lookup (GdmDisplayStore *store,
|
||||||
|
const char *id)
|
||||||
|
{
|
||||||
|
StoredDisplay *stored_display;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), NULL);
|
||||||
|
g_return_val_if_fail (id != NULL, NULL);
|
||||||
|
|
||||||
|
stored_display = g_hash_table_lookup (store->displays,
|
||||||
|
id);
|
||||||
|
if (stored_display == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stored_display->display;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplay *
|
||||||
|
gdm_display_store_find (GdmDisplayStore *store,
|
||||||
|
GdmDisplayStoreFunc predicate,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
StoredDisplay *stored_display;
|
||||||
|
FindClosure closure;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), NULL);
|
||||||
|
g_return_val_if_fail (predicate != NULL, NULL);
|
||||||
|
|
||||||
|
closure.predicate = predicate;
|
||||||
|
closure.user_data = user_data;
|
||||||
|
|
||||||
|
stored_display = g_hash_table_find (store->displays,
|
||||||
|
(GHRFunc) find_func,
|
||||||
|
&closure);
|
||||||
|
|
||||||
|
if (stored_display == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stored_display->display;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gdm_display_store_foreach_remove (GdmDisplayStore *store,
|
||||||
|
GdmDisplayStoreFunc func,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
FindClosure closure;
|
||||||
|
guint ret;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_DISPLAY_STORE (store), 0);
|
||||||
|
g_return_val_if_fail (func != NULL, 0);
|
||||||
|
|
||||||
|
closure.predicate = func;
|
||||||
|
closure.user_data = user_data;
|
||||||
|
|
||||||
|
ret = g_hash_table_foreach_remove (store->displays,
|
||||||
|
(GHRFunc) find_func,
|
||||||
|
&closure);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_display_store_add (GdmDisplayStore *store,
|
||||||
|
GdmDisplay *display)
|
||||||
|
{
|
||||||
|
char *id;
|
||||||
|
StoredDisplay *stored_display;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_DISPLAY_STORE (store));
|
||||||
|
g_return_if_fail (display != NULL);
|
||||||
|
|
||||||
|
gdm_display_get_id (display, &id, NULL);
|
||||||
|
|
||||||
|
g_debug ("GdmDisplayStore: Adding display %s to store", id);
|
||||||
|
|
||||||
|
stored_display = stored_display_new (store, display);
|
||||||
|
g_hash_table_insert (store->displays,
|
||||||
|
id,
|
||||||
|
stored_display);
|
||||||
|
|
||||||
|
g_signal_emit (G_OBJECT (store),
|
||||||
|
signals[DISPLAY_ADDED],
|
||||||
|
0,
|
||||||
|
id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_store_class_init (GdmDisplayStoreClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_display_store_finalize;
|
||||||
|
|
||||||
|
signals [DISPLAY_ADDED] =
|
||||||
|
g_signal_new ("display-added",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__STRING,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_STRING);
|
||||||
|
signals [DISPLAY_REMOVED] =
|
||||||
|
g_signal_new ("display-removed",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1, G_TYPE_OBJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_store_init (GdmDisplayStore *store)
|
||||||
|
{
|
||||||
|
store->displays = g_hash_table_new_full (g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
(GDestroyNotify)
|
||||||
|
stored_display_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_display_store_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmDisplayStore *store;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_DISPLAY_STORE (object));
|
||||||
|
|
||||||
|
store = GDM_DISPLAY_STORE (object);
|
||||||
|
|
||||||
|
g_hash_table_destroy (store->displays);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_display_store_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplayStore *
|
||||||
|
gdm_display_store_new (void)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_DISPLAY_STORE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GDM_DISPLAY_STORE (object);
|
||||||
|
}
|
69
daemon/gdm-display-store.h
Normal file
69
daemon/gdm-display-store.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_DISPLAY_STORE_H
|
||||||
|
#define __GDM_DISPLAY_STORE_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gdm-display.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_DISPLAY_STORE (gdm_display_store_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmDisplayStore, gdm_display_store, GDM, DISPLAY_STORE, GObject)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_DISPLAY_STORE_ERROR_GENERAL
|
||||||
|
} GdmDisplayStoreError;
|
||||||
|
|
||||||
|
#define GDM_DISPLAY_STORE_ERROR gdm_display_store_error_quark ()
|
||||||
|
|
||||||
|
typedef gboolean (*GdmDisplayStoreFunc) (const char *id,
|
||||||
|
GdmDisplay *display,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GQuark gdm_display_store_error_quark (void);
|
||||||
|
|
||||||
|
GdmDisplayStore * gdm_display_store_new (void);
|
||||||
|
|
||||||
|
void gdm_display_store_add (GdmDisplayStore *store,
|
||||||
|
GdmDisplay *display);
|
||||||
|
void gdm_display_store_clear (GdmDisplayStore *store);
|
||||||
|
gboolean gdm_display_store_remove (GdmDisplayStore *store,
|
||||||
|
GdmDisplay *display);
|
||||||
|
void gdm_display_store_foreach (GdmDisplayStore *store,
|
||||||
|
GdmDisplayStoreFunc func,
|
||||||
|
gpointer user_data);
|
||||||
|
guint gdm_display_store_foreach_remove (GdmDisplayStore *store,
|
||||||
|
GdmDisplayStoreFunc func,
|
||||||
|
gpointer user_data);
|
||||||
|
GdmDisplay * gdm_display_store_lookup (GdmDisplayStore *store,
|
||||||
|
const char *id);
|
||||||
|
|
||||||
|
GdmDisplay * gdm_display_store_find (GdmDisplayStore *store,
|
||||||
|
GdmDisplayStoreFunc predicate,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_DISPLAY_STORE_H */
|
1942
daemon/gdm-display.c
Normal file
1942
daemon/gdm-display.c
Normal file
File diff suppressed because it is too large
Load diff
117
daemon/gdm-display.h
Normal file
117
daemon/gdm-display.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_DISPLAY_H
|
||||||
|
#define __GDM_DISPLAY_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_DISPLAY (gdm_display_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GdmDisplay, gdm_display, GDM, DISPLAY, GObject)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GDM_DISPLAY_UNMANAGED = 0,
|
||||||
|
GDM_DISPLAY_PREPARED,
|
||||||
|
GDM_DISPLAY_MANAGED,
|
||||||
|
GDM_DISPLAY_WAITING_TO_FINISH,
|
||||||
|
GDM_DISPLAY_FINISHED,
|
||||||
|
GDM_DISPLAY_FAILED,
|
||||||
|
} GdmDisplayStatus;
|
||||||
|
|
||||||
|
struct _GdmDisplayClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/* methods */
|
||||||
|
gboolean (*prepare) (GdmDisplay *display);
|
||||||
|
void (*manage) (GdmDisplay *self);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_DISPLAY_ERROR_GENERAL,
|
||||||
|
GDM_DISPLAY_ERROR_GETTING_USER_INFO,
|
||||||
|
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
|
||||||
|
} GdmDisplayError;
|
||||||
|
|
||||||
|
#define GDM_DISPLAY_ERROR gdm_display_error_quark ()
|
||||||
|
|
||||||
|
GQuark gdm_display_error_quark (void);
|
||||||
|
|
||||||
|
int gdm_display_get_status (GdmDisplay *display);
|
||||||
|
time_t gdm_display_get_creation_time (GdmDisplay *display);
|
||||||
|
const char * gdm_display_get_session_id (GdmDisplay *display);
|
||||||
|
gboolean gdm_display_create_authority (GdmDisplay *display);
|
||||||
|
gboolean gdm_display_prepare (GdmDisplay *display);
|
||||||
|
gboolean gdm_display_manage (GdmDisplay *display);
|
||||||
|
gboolean gdm_display_finish (GdmDisplay *display);
|
||||||
|
gboolean gdm_display_unmanage (GdmDisplay *display);
|
||||||
|
|
||||||
|
GDBusObjectSkeleton *gdm_display_get_object_skeleton (GdmDisplay *display);
|
||||||
|
|
||||||
|
/* exported to bus */
|
||||||
|
gboolean gdm_display_get_id (GdmDisplay *display,
|
||||||
|
char **id,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_get_remote_hostname (GdmDisplay *display,
|
||||||
|
char **hostname,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_get_x11_display_number (GdmDisplay *display,
|
||||||
|
int *number,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_get_x11_display_name (GdmDisplay *display,
|
||||||
|
char **x11_display,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_get_seat_id (GdmDisplay *display,
|
||||||
|
char **seat_id,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_is_local (GdmDisplay *display,
|
||||||
|
gboolean *local,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_is_initial (GdmDisplay *display,
|
||||||
|
gboolean *initial,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean gdm_display_get_x11_cookie (GdmDisplay *display,
|
||||||
|
const char **x11_cookie,
|
||||||
|
gsize *x11_cookie_size,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_get_x11_authority_file (GdmDisplay *display,
|
||||||
|
char **filename,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_add_user_authorization (GdmDisplay *display,
|
||||||
|
const char *username,
|
||||||
|
char **filename,
|
||||||
|
GError **error);
|
||||||
|
gboolean gdm_display_remove_user_authorization (GdmDisplay *display,
|
||||||
|
const char *username,
|
||||||
|
GError **error);
|
||||||
|
void gdm_display_start_greeter_session (GdmDisplay *display);
|
||||||
|
void gdm_display_stop_greeter_session (GdmDisplay *display);
|
||||||
|
|
||||||
|
gboolean gdm_display_connect (GdmDisplay *self);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_DISPLAY_H */
|
23
daemon/gdm-display.xml
Normal file
23
daemon/gdm-display.xml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node>
|
||||||
|
<interface name="org.gnome.DisplayManager.Display">
|
||||||
|
<method name="GetId">
|
||||||
|
<arg name="id" direction="out" type="o"/>
|
||||||
|
</method>
|
||||||
|
<method name="GetX11DisplayName">
|
||||||
|
<arg name="name" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="GetSeatId">
|
||||||
|
<arg name="filename" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="IsInitial">
|
||||||
|
<arg name="initial" direction="out" type="b"/>
|
||||||
|
</method>
|
||||||
|
<method name="GetRemoteHostname">
|
||||||
|
<arg name="hostname" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="IsLocal">
|
||||||
|
<arg name="local" direction="out" type="b"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
</node>
|
1032
daemon/gdm-launch-environment.c
Normal file
1032
daemon/gdm-launch-environment.c
Normal file
File diff suppressed because it is too large
Load diff
54
daemon/gdm-launch-environment.h
Normal file
54
daemon/gdm-launch-environment.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_LAUNCH_ENVIRONMENT_H
|
||||||
|
#define __GDM_LAUNCH_ENVIRONMENT_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gdm-session.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_LAUNCH_ENVIRONMENT (gdm_launch_environment_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmLaunchEnvironment, gdm_launch_environment, GDM, LAUNCH_ENVIRONMENT, GObject)
|
||||||
|
|
||||||
|
gboolean gdm_launch_environment_start (GdmLaunchEnvironment *launch_environment);
|
||||||
|
gboolean gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment);
|
||||||
|
GdmSession * gdm_launch_environment_get_session (GdmLaunchEnvironment *launch_environment);
|
||||||
|
char * gdm_launch_environment_get_session_id (GdmLaunchEnvironment *launch_environment);
|
||||||
|
|
||||||
|
GdmLaunchEnvironment *gdm_create_greeter_launch_environment (const char *display_name,
|
||||||
|
const char *seat_id,
|
||||||
|
const char *session_type,
|
||||||
|
const char *display_hostname,
|
||||||
|
gboolean display_is_local);
|
||||||
|
GdmLaunchEnvironment *gdm_create_initial_setup_launch_environment (const char *display_name,
|
||||||
|
const char *seat_id,
|
||||||
|
const char *session_type,
|
||||||
|
const char *display_hostname,
|
||||||
|
gboolean display_is_local);
|
||||||
|
GdmLaunchEnvironment *gdm_create_chooser_launch_environment (const char *display_name,
|
||||||
|
const char *seat_id,
|
||||||
|
const char *display_hostname);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_LAUNCH_ENVIRONMENT_H */
|
292
daemon/gdm-legacy-display.c
Normal file
292
daemon/gdm-legacy-display.c
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
#include "gdm-display.h"
|
||||||
|
#include "gdm-launch-environment.h"
|
||||||
|
#include "gdm-legacy-display.h"
|
||||||
|
#include "gdm-local-display-glue.h"
|
||||||
|
#include "gdm-server.h"
|
||||||
|
#include "gdm-settings-direct.h"
|
||||||
|
#include "gdm-settings-keys.h"
|
||||||
|
|
||||||
|
struct _GdmLegacyDisplay
|
||||||
|
{
|
||||||
|
GdmDisplay parent;
|
||||||
|
|
||||||
|
GdmDBusLocalDisplay *skeleton;
|
||||||
|
|
||||||
|
GdmServer *server;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_legacy_display_class_init (GdmLegacyDisplayClass *klass);
|
||||||
|
static void gdm_legacy_display_init (GdmLegacyDisplay *legacy_display);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmLegacyDisplay, gdm_legacy_display, GDM_TYPE_DISPLAY)
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gdm_legacy_display_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmLegacyDisplay *display;
|
||||||
|
|
||||||
|
display = GDM_LEGACY_DISPLAY (G_OBJECT_CLASS (gdm_legacy_display_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
display->skeleton = GDM_DBUS_LOCAL_DISPLAY (gdm_dbus_local_display_skeleton_new ());
|
||||||
|
|
||||||
|
g_dbus_object_skeleton_add_interface (gdm_display_get_object_skeleton (GDM_DISPLAY (display)),
|
||||||
|
G_DBUS_INTERFACE_SKELETON (display->skeleton));
|
||||||
|
|
||||||
|
return G_OBJECT (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_legacy_display_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmLegacyDisplay *display = GDM_LEGACY_DISPLAY (object);
|
||||||
|
|
||||||
|
g_clear_object (&display->skeleton);
|
||||||
|
g_clear_object (&display->server);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_legacy_display_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_legacy_display_prepare (GdmDisplay *display)
|
||||||
|
{
|
||||||
|
GdmLegacyDisplay *self = GDM_LEGACY_DISPLAY (display);
|
||||||
|
g_autoptr(GdmLaunchEnvironment) launch_environment = NULL;
|
||||||
|
g_autofree char *display_name = NULL;
|
||||||
|
g_autofree gchar *seat_id = NULL;
|
||||||
|
gboolean doing_initial_setup = FALSE;
|
||||||
|
|
||||||
|
g_object_get (self,
|
||||||
|
"x11-display-name", &display_name,
|
||||||
|
"seat-id", &seat_id,
|
||||||
|
"doing-initial-setup", &doing_initial_setup,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!doing_initial_setup) {
|
||||||
|
launch_environment = gdm_create_greeter_launch_environment (display_name,
|
||||||
|
seat_id,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
TRUE);
|
||||||
|
} else {
|
||||||
|
launch_environment = gdm_create_initial_setup_launch_environment (display_name,
|
||||||
|
seat_id,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set (self, "launch-environment", launch_environment, NULL);
|
||||||
|
|
||||||
|
if (!gdm_display_create_authority (display)) {
|
||||||
|
g_warning ("Unable to set up access control for display %s",
|
||||||
|
display_name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDM_DISPLAY_CLASS (gdm_legacy_display_parent_class)->prepare (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_server_ready (GdmServer *server,
|
||||||
|
GdmLegacyDisplay *self)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
ret = gdm_display_connect (GDM_DISPLAY (self));
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
g_debug ("GdmDisplay: could not connect to display");
|
||||||
|
gdm_display_unmanage (GDM_DISPLAY (self));
|
||||||
|
} else {
|
||||||
|
g_autoptr(GdmLaunchEnvironment) launch_environment = NULL;
|
||||||
|
g_autofree char *display_device = NULL;
|
||||||
|
|
||||||
|
display_device = gdm_server_get_display_device (server);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (self),
|
||||||
|
"launch-environment", &launch_environment,
|
||||||
|
NULL);
|
||||||
|
g_object_set (G_OBJECT (launch_environment),
|
||||||
|
"x11-display-device",
|
||||||
|
display_device,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_debug ("GdmDisplay: connected to display");
|
||||||
|
g_object_set (G_OBJECT (self), "status", GDM_DISPLAY_MANAGED, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_server_exited (GdmServer *server,
|
||||||
|
int exit_code,
|
||||||
|
GdmDisplay *self)
|
||||||
|
{
|
||||||
|
g_debug ("GdmDisplay: server exited with code %d\n", exit_code);
|
||||||
|
|
||||||
|
gdm_display_unmanage (GDM_DISPLAY (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_server_died (GdmServer *server,
|
||||||
|
int signal_number,
|
||||||
|
GdmDisplay *self)
|
||||||
|
{
|
||||||
|
g_debug ("GdmDisplay: server died with signal %d, (%s)",
|
||||||
|
signal_number,
|
||||||
|
g_strsignal (signal_number));
|
||||||
|
|
||||||
|
gdm_display_unmanage (GDM_DISPLAY (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_legacy_display_manage (GdmDisplay *display)
|
||||||
|
{
|
||||||
|
GdmLegacyDisplay *self = GDM_LEGACY_DISPLAY (display);
|
||||||
|
g_autofree char *display_name = NULL;
|
||||||
|
g_autofree char *auth_file = NULL;
|
||||||
|
g_autofree char *seat_id = NULL;
|
||||||
|
gboolean is_initial;
|
||||||
|
gboolean res;
|
||||||
|
gboolean disable_tcp;
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (self),
|
||||||
|
"x11-display-name", &display_name,
|
||||||
|
"x11-authority-file", &auth_file,
|
||||||
|
"seat-id", &seat_id,
|
||||||
|
"is-initial", &is_initial,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
self->server = gdm_server_new (display_name, seat_id, auth_file, is_initial);
|
||||||
|
|
||||||
|
disable_tcp = TRUE;
|
||||||
|
if (gdm_settings_direct_get_boolean (GDM_KEY_DISALLOW_TCP, &disable_tcp)) {
|
||||||
|
g_object_set (self->server,
|
||||||
|
"disable-tcp", disable_tcp,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (self->server,
|
||||||
|
"exited",
|
||||||
|
G_CALLBACK (on_server_exited),
|
||||||
|
self);
|
||||||
|
g_signal_connect (self->server,
|
||||||
|
"died",
|
||||||
|
G_CALLBACK (on_server_died),
|
||||||
|
self);
|
||||||
|
g_signal_connect (self->server,
|
||||||
|
"ready",
|
||||||
|
G_CALLBACK (on_server_ready),
|
||||||
|
self);
|
||||||
|
|
||||||
|
res = gdm_server_start (self->server);
|
||||||
|
if (! res) {
|
||||||
|
g_warning (_("Could not start the X "
|
||||||
|
"server (your graphical environment) "
|
||||||
|
"due to an internal error. "
|
||||||
|
"Please contact your system administrator "
|
||||||
|
"or check your syslog to diagnose. "
|
||||||
|
"In the meantime this display will be "
|
||||||
|
"disabled. Please restart GDM when "
|
||||||
|
"the problem is corrected."));
|
||||||
|
gdm_display_unmanage (GDM_DISPLAY (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GdmDisplay: Started X server");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_legacy_display_class_init (GdmLegacyDisplayClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GdmDisplayClass *display_class = GDM_DISPLAY_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->constructor = gdm_legacy_display_constructor;
|
||||||
|
object_class->finalize = gdm_legacy_display_finalize;
|
||||||
|
|
||||||
|
display_class->prepare = gdm_legacy_display_prepare;
|
||||||
|
display_class->manage = gdm_legacy_display_manage;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_display_status_changed (GdmLegacyDisplay *self)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = gdm_display_get_status (GDM_DISPLAY (self));
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case GDM_DISPLAY_UNMANAGED:
|
||||||
|
if (self->server != NULL)
|
||||||
|
gdm_server_stop (self->server);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_legacy_display_init (GdmLegacyDisplay *legacy_display)
|
||||||
|
{
|
||||||
|
g_signal_connect (legacy_display, "notify::status",
|
||||||
|
G_CALLBACK (on_display_status_changed),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplay *
|
||||||
|
gdm_legacy_display_new (int display_number)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
g_autofree char *x11_display = NULL;
|
||||||
|
|
||||||
|
x11_display = g_strdup_printf (":%d", display_number);
|
||||||
|
object = g_object_new (GDM_TYPE_LEGACY_DISPLAY,
|
||||||
|
"x11-display-number", display_number,
|
||||||
|
"x11-display-name", x11_display,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GDM_DISPLAY (object);
|
||||||
|
}
|
38
daemon/gdm-legacy-display.h
Normal file
38
daemon/gdm-legacy-display.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_LEGACY_DISPLAY_H
|
||||||
|
#define __GDM_LEGACY_DISPLAY_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gdm-display.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_LEGACY_DISPLAY (gdm_legacy_display_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmLegacyDisplay, gdm_legacy_display, GDM, LEGACY_DISPLAY, GdmDisplay)
|
||||||
|
|
||||||
|
GdmDisplay * gdm_legacy_display_new (int display_number);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_LEGACY_DISPLAY_H */
|
1722
daemon/gdm-local-display-factory.c
Normal file
1722
daemon/gdm-local-display-factory.c
Normal file
File diff suppressed because it is too large
Load diff
51
daemon/gdm-local-display-factory.h
Normal file
51
daemon/gdm-local-display-factory.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_LOCAL_DISPLAY_FACTORY_H
|
||||||
|
#define __GDM_LOCAL_DISPLAY_FACTORY_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display-factory.h"
|
||||||
|
#include "gdm-display-store.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_LOCAL_DISPLAY_FACTORY (gdm_local_display_factory_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM, LOCAL_DISPLAY_FACTORY, GdmDisplayFactory)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_LOCAL_DISPLAY_FACTORY_ERROR_GENERAL
|
||||||
|
} GdmLocalDisplayFactoryError;
|
||||||
|
|
||||||
|
#define GDM_LOCAL_DISPLAY_FACTORY_ERROR gdm_local_display_factory_error_quark ()
|
||||||
|
|
||||||
|
GQuark gdm_local_display_factory_error_quark (void);
|
||||||
|
|
||||||
|
GdmLocalDisplayFactory * gdm_local_display_factory_new (GdmDisplayStore *display_store);
|
||||||
|
|
||||||
|
gboolean gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
|
||||||
|
char **id,
|
||||||
|
GError **error);
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_LOCAL_DISPLAY_FACTORY_H */
|
8
daemon/gdm-local-display-factory.xml
Normal file
8
daemon/gdm-local-display-factory.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node name="/org/gnome/DisplayManager/LocalDisplayFactory">
|
||||||
|
<interface name="org.gnome.DisplayManager.LocalDisplayFactory">
|
||||||
|
<method name="CreateTransientDisplay">
|
||||||
|
<arg name="id" direction="out" type="o"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
</node>
|
162
daemon/gdm-local-display.c
Normal file
162
daemon/gdm-local-display.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
#include "gdm-display.h"
|
||||||
|
#include "gdm-launch-environment.h"
|
||||||
|
#include "gdm-local-display.h"
|
||||||
|
#include "gdm-local-display-glue.h"
|
||||||
|
#include "gdm-settings-direct.h"
|
||||||
|
#include "gdm-settings-keys.h"
|
||||||
|
|
||||||
|
struct _GdmLocalDisplay
|
||||||
|
{
|
||||||
|
GdmDisplay parent;
|
||||||
|
GdmDBusLocalDisplay *skeleton;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_local_display_class_init (GdmLocalDisplayClass *klass);
|
||||||
|
static void gdm_local_display_init (GdmLocalDisplay *local_display);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmLocalDisplay, gdm_local_display, GDM_TYPE_DISPLAY)
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gdm_local_display_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmLocalDisplay *display;
|
||||||
|
|
||||||
|
display = GDM_LOCAL_DISPLAY (G_OBJECT_CLASS (gdm_local_display_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
display->skeleton = GDM_DBUS_LOCAL_DISPLAY (gdm_dbus_local_display_skeleton_new ());
|
||||||
|
|
||||||
|
g_dbus_object_skeleton_add_interface (gdm_display_get_object_skeleton (GDM_DISPLAY (display)),
|
||||||
|
G_DBUS_INTERFACE_SKELETON (display->skeleton));
|
||||||
|
|
||||||
|
return G_OBJECT (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_local_display_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmLocalDisplay *display = GDM_LOCAL_DISPLAY (object);
|
||||||
|
|
||||||
|
g_clear_object (&display->skeleton);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_local_display_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_local_display_prepare (GdmDisplay *display)
|
||||||
|
{
|
||||||
|
GdmLocalDisplay *self = GDM_LOCAL_DISPLAY (display);
|
||||||
|
GdmLaunchEnvironment *launch_environment;
|
||||||
|
char *seat_id;
|
||||||
|
char *session_class;
|
||||||
|
char *session_type;
|
||||||
|
gboolean doing_initial_setup = FALSE;
|
||||||
|
|
||||||
|
seat_id = NULL;
|
||||||
|
|
||||||
|
g_object_get (self,
|
||||||
|
"seat-id", &seat_id,
|
||||||
|
"doing-initial-setup", &doing_initial_setup,
|
||||||
|
"session-class", &session_class,
|
||||||
|
"session-type", &session_type,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (g_strcmp0 (session_class, "greeter") != 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("doing initial setup? %s", doing_initial_setup? "yes" : "no");
|
||||||
|
|
||||||
|
if (!doing_initial_setup) {
|
||||||
|
launch_environment = gdm_create_greeter_launch_environment (NULL,
|
||||||
|
seat_id,
|
||||||
|
session_type,
|
||||||
|
NULL,
|
||||||
|
TRUE);
|
||||||
|
} else {
|
||||||
|
launch_environment = gdm_create_initial_setup_launch_environment (NULL,
|
||||||
|
seat_id,
|
||||||
|
session_type,
|
||||||
|
NULL,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set (self, "launch-environment", launch_environment, NULL);
|
||||||
|
g_object_unref (launch_environment);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_free (seat_id);
|
||||||
|
g_free (session_class);
|
||||||
|
g_free (session_type);
|
||||||
|
|
||||||
|
return GDM_DISPLAY_CLASS (gdm_local_display_parent_class)->prepare (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_local_display_class_init (GdmLocalDisplayClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GdmDisplayClass *display_class = GDM_DISPLAY_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->constructor = gdm_local_display_constructor;
|
||||||
|
object_class->finalize = gdm_local_display_finalize;
|
||||||
|
|
||||||
|
display_class->prepare = gdm_local_display_prepare;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_local_display_init (GdmLocalDisplay *local_display)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplay *
|
||||||
|
gdm_local_display_new (void)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_LOCAL_DISPLAY, NULL);
|
||||||
|
|
||||||
|
return GDM_DISPLAY (object);
|
||||||
|
}
|
38
daemon/gdm-local-display.h
Normal file
38
daemon/gdm-local-display.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_LOCAL_DISPLAY_H
|
||||||
|
#define __GDM_LOCAL_DISPLAY_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include "gdm-display.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_LOCAL_DISPLAY (gdm_local_display_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmLocalDisplay, gdm_local_display, GDM, LOCAL_DISPLAY, GdmDisplay)
|
||||||
|
|
||||||
|
GdmDisplay * gdm_local_display_new (void);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_LOCAL_DISPLAY_H */
|
5
daemon/gdm-local-display.xml
Normal file
5
daemon/gdm-local-display.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node>
|
||||||
|
<interface name="org.gnome.DisplayManager.LocalDisplay">
|
||||||
|
</interface>
|
||||||
|
</node>
|
3051
daemon/gdm-manager.c
Normal file
3051
daemon/gdm-manager.c
Normal file
File diff suppressed because it is too large
Load diff
61
daemon/gdm-manager.h
Normal file
61
daemon/gdm-manager.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_MANAGER_H
|
||||||
|
#define __GDM_MANAGER_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display.h"
|
||||||
|
#include "gdm-manager-glue.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_MANAGER (gdm_manager_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmManager, gdm_manager, GDM, MANAGER, GdmDBusManagerSkeleton)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_MANAGER_ERROR_GENERAL
|
||||||
|
} GdmManagerError;
|
||||||
|
|
||||||
|
#define GDM_MANAGER_ERROR gdm_manager_error_quark ()
|
||||||
|
|
||||||
|
GQuark gdm_manager_error_quark (void);
|
||||||
|
|
||||||
|
GdmManager * gdm_manager_new (void);
|
||||||
|
void gdm_manager_start (GdmManager *manager);
|
||||||
|
void gdm_manager_stop (GdmManager *manager);
|
||||||
|
|
||||||
|
void gdm_manager_set_xdmcp_enabled (GdmManager *manager,
|
||||||
|
gboolean enabled);
|
||||||
|
void gdm_manager_set_show_local_greeter (GdmManager *manager,
|
||||||
|
gboolean show_local_greeter);
|
||||||
|
void gdm_manager_set_remote_login_enabled (GdmManager *manager,
|
||||||
|
gboolean enabled);
|
||||||
|
gboolean gdm_manager_get_displays (GdmManager *manager,
|
||||||
|
GPtrArray **displays,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_MANAGER_H */
|
19
daemon/gdm-manager.xml
Normal file
19
daemon/gdm-manager.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node name="/org/gnome/DisplayManager/Manager">
|
||||||
|
<interface name="org.gnome.DisplayManager.Manager">
|
||||||
|
<method name="RegisterDisplay">
|
||||||
|
<arg name="details" direction="in" type="a{ss}"/>
|
||||||
|
</method>
|
||||||
|
<method name="RegisterSession">
|
||||||
|
<arg name="details" direction="in" type="a{sv}"/>
|
||||||
|
</method>
|
||||||
|
<method name="OpenSession">
|
||||||
|
<arg name="address" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="OpenReauthenticationChannel">
|
||||||
|
<arg name="username" direction="in" type="s"/>
|
||||||
|
<arg name="address" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<property name="Version" type="s" access="read"/>
|
||||||
|
</interface>
|
||||||
|
</node>
|
357
daemon/gdm-remote-display-factory.c
Normal file
357
daemon/gdm-remote-display-factory.c
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Joan Torres <joan.torres@suse.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gdm-remote-display.h"
|
||||||
|
#include "gdm-remote-display-factory.h"
|
||||||
|
#include "gdm-remote-display-factory-glue.h"
|
||||||
|
|
||||||
|
#define GDM_REMOTE_DISPLAY_FACTORY_DBUS_PATH "/org/gnome/DisplayManager/RemoteDisplayFactory"
|
||||||
|
|
||||||
|
struct _GdmRemoteDisplayFactory
|
||||||
|
{
|
||||||
|
GdmDisplayFactory parent;
|
||||||
|
|
||||||
|
GdmDBusRemoteDisplayFactory *skeleton;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
|
||||||
|
int remote_displays_count;
|
||||||
|
|
||||||
|
gboolean suspend_inhibited;
|
||||||
|
int inhibit_suspend_fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_remote_display_factory_class_init (GdmRemoteDisplayFactoryClass *klass);
|
||||||
|
static void gdm_remote_display_factory_init (GdmRemoteDisplayFactory *factory);
|
||||||
|
static void gdm_remote_display_factory_finalize (GObject *object);
|
||||||
|
|
||||||
|
static gpointer remote_display_factory_object = NULL;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmRemoteDisplayFactory, gdm_remote_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_display_status_changed (GdmDisplay *display,
|
||||||
|
GParamSpec *arg1,
|
||||||
|
GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
g_debug ("GdmRemoteDisplayFactory: remote display status changed: %d",
|
||||||
|
gdm_display_get_status (display));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_remote_display_factory_create_remote_display (GdmRemoteDisplayFactory *factory,
|
||||||
|
const char *remote_id)
|
||||||
|
{
|
||||||
|
GdmDisplay *display = NULL;
|
||||||
|
GdmDisplayStore *store;
|
||||||
|
|
||||||
|
g_debug ("GdmRemoteDisplayFactory: Creating remote display");
|
||||||
|
|
||||||
|
display = gdm_remote_display_new (remote_id);
|
||||||
|
|
||||||
|
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||||
|
gdm_display_store_add (store, display);
|
||||||
|
|
||||||
|
if (!gdm_display_prepare (display)) {
|
||||||
|
gdm_display_unmanage (display);
|
||||||
|
g_object_unref (display);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect_after (display,
|
||||||
|
"notify::status",
|
||||||
|
G_CALLBACK (on_display_status_changed),
|
||||||
|
factory);
|
||||||
|
|
||||||
|
g_object_unref (display);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_create_remote_display (GdmDBusRemoteDisplayFactory *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
const char *remote_id,
|
||||||
|
GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
if (!gdm_remote_display_factory_create_remote_display (factory, remote_id))
|
||||||
|
g_dbus_method_invocation_return_error_literal (invocation,
|
||||||
|
G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Error creating remote display");
|
||||||
|
else
|
||||||
|
gdm_dbus_remote_display_factory_complete_create_remote_display (factory->skeleton,
|
||||||
|
invocation);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
register_factory (GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
factory->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
|
if (factory->connection == NULL) {
|
||||||
|
g_critical ("Error getting system bus: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory->skeleton = GDM_DBUS_REMOTE_DISPLAY_FACTORY (gdm_dbus_remote_display_factory_skeleton_new ());
|
||||||
|
|
||||||
|
g_signal_connect (factory->skeleton,
|
||||||
|
"handle-create-remote-display",
|
||||||
|
G_CALLBACK (handle_create_remote_display),
|
||||||
|
factory);
|
||||||
|
|
||||||
|
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (factory->skeleton),
|
||||||
|
factory->connection,
|
||||||
|
GDM_REMOTE_DISPLAY_FACTORY_DBUS_PATH,
|
||||||
|
&error)) {
|
||||||
|
g_critical ("Error exporting RemoteDisplayFactory object: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_remote_display_factory_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmRemoteDisplayFactory *factory;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_REMOTE_DISPLAY_FACTORY (object));
|
||||||
|
|
||||||
|
factory = GDM_REMOTE_DISPLAY_FACTORY (object);
|
||||||
|
|
||||||
|
g_return_if_fail (factory != NULL);
|
||||||
|
|
||||||
|
g_clear_object (&factory->connection);
|
||||||
|
g_clear_object (&factory->skeleton);
|
||||||
|
|
||||||
|
if (factory->inhibit_suspend_fd != -1)
|
||||||
|
close (factory->inhibit_suspend_fd);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_remote_display_factory_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gdm_remote_display_factory_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmRemoteDisplayFactory *factory;
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
factory = GDM_REMOTE_DISPLAY_FACTORY (G_OBJECT_CLASS (gdm_remote_display_factory_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
res = register_factory (factory);
|
||||||
|
if (!res) {
|
||||||
|
g_warning ("Unable to register remote display factory with system bus");
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_OBJECT (factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_inhibit_suspend_done (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GDBusProxy *proxy = G_DBUS_PROXY (source);
|
||||||
|
GdmRemoteDisplayFactory *factory = user_data;
|
||||||
|
g_autoptr (GUnixFDList) fd_list = NULL;
|
||||||
|
g_autoptr (GVariant) res = NULL;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy,
|
||||||
|
&fd_list,
|
||||||
|
result,
|
||||||
|
&error);
|
||||||
|
if (!res) {
|
||||||
|
g_warning ("Unable to inhibit suspend: %s", error->message);
|
||||||
|
factory->suspend_inhibited = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (res, "(h)", &idx);
|
||||||
|
factory->inhibit_suspend_fd = g_unix_fd_list_get (fd_list, idx, &error);
|
||||||
|
if (factory->inhibit_suspend_fd == -1) {
|
||||||
|
g_warning ("Failed to receive system inhibitor fd: %s", error->message);
|
||||||
|
factory->suspend_inhibited = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
inhibit_suspend (GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
g_autoptr (GDBusProxy) proxy = NULL;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
if (factory->suspend_inhibited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
NULL,
|
||||||
|
"org.freedesktop.login1",
|
||||||
|
"/org/freedesktop/login1",
|
||||||
|
"org.freedesktop.login1.Manager",
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
if (!proxy) {
|
||||||
|
g_warning ("Failed to acquire login1 manager proxy: %s", error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory->suspend_inhibited = TRUE;
|
||||||
|
g_dbus_proxy_call_with_unix_fd_list (proxy,
|
||||||
|
"Inhibit",
|
||||||
|
g_variant_new ("(ssss)",
|
||||||
|
"sleep",
|
||||||
|
g_get_user_name (),
|
||||||
|
"Remote sessions would die on suspend",
|
||||||
|
"block"),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
G_MAXINT,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
on_inhibit_suspend_done,
|
||||||
|
factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_display_added (GdmDisplayStore *store,
|
||||||
|
const char *id,
|
||||||
|
GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
GdmDisplay *display = gdm_display_store_lookup (store, id);
|
||||||
|
|
||||||
|
if (!GDM_IS_REMOTE_DISPLAY (display))
|
||||||
|
return;
|
||||||
|
|
||||||
|
factory->remote_displays_count++;
|
||||||
|
|
||||||
|
if (factory->remote_displays_count > 0)
|
||||||
|
inhibit_suspend (factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninhibit_suspend (GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
if (factory->inhibit_suspend_fd == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
close (factory->inhibit_suspend_fd);
|
||||||
|
factory->inhibit_suspend_fd = -1;
|
||||||
|
factory->suspend_inhibited = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_display_removed (GdmDisplayStore *display_store,
|
||||||
|
GdmDisplay *display,
|
||||||
|
GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
g_assert (factory->remote_displays_count >= 0);
|
||||||
|
|
||||||
|
if (!GDM_IS_REMOTE_DISPLAY (display))
|
||||||
|
return;
|
||||||
|
|
||||||
|
factory->remote_displays_count--;
|
||||||
|
|
||||||
|
if (factory->remote_displays_count == 0)
|
||||||
|
uninhibit_suspend (factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_remote_display_factory_start (GdmDisplayFactory *base_factory)
|
||||||
|
{
|
||||||
|
GdmRemoteDisplayFactory *factory = GDM_REMOTE_DISPLAY_FACTORY (base_factory);
|
||||||
|
GdmDisplayStore *store;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_REMOTE_DISPLAY_FACTORY (factory), FALSE);
|
||||||
|
|
||||||
|
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||||
|
|
||||||
|
g_signal_connect_object (G_OBJECT (store),
|
||||||
|
"display-added",
|
||||||
|
G_CALLBACK (on_display_added),
|
||||||
|
factory,
|
||||||
|
G_CONNECT_DEFAULT);
|
||||||
|
|
||||||
|
g_signal_connect_object (G_OBJECT (store),
|
||||||
|
"display-removed",
|
||||||
|
G_CALLBACK (on_display_removed),
|
||||||
|
factory,
|
||||||
|
G_CONNECT_DEFAULT);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_remote_display_factory_stop (GdmDisplayFactory *base_factory)
|
||||||
|
{
|
||||||
|
GdmRemoteDisplayFactory *factory = GDM_REMOTE_DISPLAY_FACTORY (base_factory);
|
||||||
|
g_return_val_if_fail (GDM_IS_REMOTE_DISPLAY_FACTORY (factory), FALSE);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_remote_display_factory_class_init (GdmRemoteDisplayFactoryClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GdmDisplayFactoryClass *factory_class = GDM_DISPLAY_FACTORY_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_remote_display_factory_finalize;
|
||||||
|
object_class->constructor = gdm_remote_display_factory_constructor;
|
||||||
|
|
||||||
|
factory_class->start = gdm_remote_display_factory_start;
|
||||||
|
factory_class->stop = gdm_remote_display_factory_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_remote_display_factory_init (GdmRemoteDisplayFactory *factory)
|
||||||
|
{
|
||||||
|
factory->inhibit_suspend_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmRemoteDisplayFactory *
|
||||||
|
gdm_remote_display_factory_new (GdmDisplayStore *store)
|
||||||
|
{
|
||||||
|
if (remote_display_factory_object != NULL) {
|
||||||
|
g_object_ref (remote_display_factory_object);
|
||||||
|
} else {
|
||||||
|
remote_display_factory_object = g_object_new (GDM_TYPE_REMOTE_DISPLAY_FACTORY,
|
||||||
|
"display-store", store,
|
||||||
|
NULL);
|
||||||
|
g_object_add_weak_pointer (remote_display_factory_object,
|
||||||
|
(gpointer *) &remote_display_factory_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GDM_REMOTE_DISPLAY_FACTORY (remote_display_factory_object);
|
||||||
|
}
|
39
daemon/gdm-remote-display-factory.h
Normal file
39
daemon/gdm-remote-display-factory.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Joan Torres <joan.torres@suse.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_REMOTE_DISPLAY_FACTORY_H
|
||||||
|
#define __GDM_REMOTE_DISPLAY_FACTORY_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display-factory.h"
|
||||||
|
#include "gdm-display-store.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_REMOTE_DISPLAY_FACTORY (gdm_remote_display_factory_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmRemoteDisplayFactory, gdm_remote_display_factory, GDM, REMOTE_DISPLAY_FACTORY, GdmDisplayFactory)
|
||||||
|
|
||||||
|
GdmRemoteDisplayFactory * gdm_remote_display_factory_new (GdmDisplayStore *display_store);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_REMOTE_DISPLAY_FACTORY_H */
|
8
daemon/gdm-remote-display-factory.xml
Normal file
8
daemon/gdm-remote-display-factory.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node name="/org/gnome/DisplayManager/RemoteDisplayFactory">
|
||||||
|
<interface name="org.gnome.DisplayManager.RemoteDisplayFactory">
|
||||||
|
<method name="CreateRemoteDisplay">
|
||||||
|
<arg name="remote_id" direction="in" type="o"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
</node>
|
152
daemon/gdm-remote-display.c
Normal file
152
daemon/gdm-remote-display.c
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Joan Torres <joan.torres@suse.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-display.h"
|
||||||
|
#include "gdm-launch-environment.h"
|
||||||
|
#include "gdm-remote-display.h"
|
||||||
|
#include "gdm-remote-display-glue.h"
|
||||||
|
|
||||||
|
struct _GdmRemoteDisplay
|
||||||
|
{
|
||||||
|
GdmDisplay parent;
|
||||||
|
|
||||||
|
GdmDBusRemoteDisplay *skeleton;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_remote_display_class_init (GdmRemoteDisplayClass *klass);
|
||||||
|
static void gdm_remote_display_init (GdmRemoteDisplay *remote_display);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmRemoteDisplay, gdm_remote_display, GDM_TYPE_DISPLAY)
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_remote_display_get_remote_id (GdmRemoteDisplay *display)
|
||||||
|
{
|
||||||
|
g_autofree char *remote_id = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_REMOTE_DISPLAY (display), NULL);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (display->skeleton),
|
||||||
|
"remote-id", &remote_id,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return g_steal_pointer (&remote_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_remote_display_set_remote_id (GdmRemoteDisplay *display,
|
||||||
|
const char *remote_id)
|
||||||
|
{
|
||||||
|
g_object_set (G_OBJECT (display->skeleton), "remote-id", remote_id, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
gdm_remote_display_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam *construct_properties)
|
||||||
|
{
|
||||||
|
GdmRemoteDisplay *display;
|
||||||
|
|
||||||
|
display = GDM_REMOTE_DISPLAY (G_OBJECT_CLASS (gdm_remote_display_parent_class)->constructor (type,
|
||||||
|
n_construct_properties,
|
||||||
|
construct_properties));
|
||||||
|
|
||||||
|
display->skeleton = GDM_DBUS_REMOTE_DISPLAY (gdm_dbus_remote_display_skeleton_new ());
|
||||||
|
|
||||||
|
g_dbus_object_skeleton_add_interface (gdm_display_get_object_skeleton (GDM_DISPLAY (display)),
|
||||||
|
G_DBUS_INTERFACE_SKELETON (display->skeleton));
|
||||||
|
|
||||||
|
g_object_bind_property (display, "session-id", display->skeleton, "session-id", G_BINDING_SYNC_CREATE);
|
||||||
|
|
||||||
|
return G_OBJECT (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_remote_display_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmRemoteDisplay *display = GDM_REMOTE_DISPLAY (object);
|
||||||
|
|
||||||
|
g_clear_object (&display->skeleton);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_remote_display_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_remote_display_prepare (GdmDisplay *display)
|
||||||
|
{
|
||||||
|
GdmRemoteDisplay *self = GDM_REMOTE_DISPLAY (display);
|
||||||
|
g_autoptr (GdmLaunchEnvironment) launch_environment = NULL;
|
||||||
|
g_autofree char *session_type = NULL;
|
||||||
|
|
||||||
|
g_object_get (self,
|
||||||
|
"session-type", &session_type,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
launch_environment = gdm_create_greeter_launch_environment (NULL,
|
||||||
|
NULL,
|
||||||
|
session_type,
|
||||||
|
NULL,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
g_object_set (self, "launch-environment", launch_environment, NULL);
|
||||||
|
|
||||||
|
return GDM_DISPLAY_CLASS (gdm_remote_display_parent_class)->prepare (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_remote_display_class_init (GdmRemoteDisplayClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GdmDisplayClass *display_class = GDM_DISPLAY_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->constructor = gdm_remote_display_constructor;
|
||||||
|
object_class->finalize = gdm_remote_display_finalize;
|
||||||
|
|
||||||
|
display_class->prepare = gdm_remote_display_prepare;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_remote_display_init (GdmRemoteDisplay *remote_display)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmDisplay *
|
||||||
|
gdm_remote_display_new (const char *remote_id)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
GdmRemoteDisplay *self;
|
||||||
|
|
||||||
|
const char *session_types[] = { "wayland", NULL };
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_REMOTE_DISPLAY,
|
||||||
|
"is-local", FALSE,
|
||||||
|
"session-type", session_types[0],
|
||||||
|
"supported-session-types", session_types,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
self = GDM_REMOTE_DISPLAY (object);
|
||||||
|
g_object_set (G_OBJECT (self->skeleton), "remote-id", remote_id, NULL);
|
||||||
|
|
||||||
|
return GDM_DISPLAY (object);
|
||||||
|
}
|
||||||
|
|
45
daemon/gdm-remote-display.h
Normal file
45
daemon/gdm-remote-display.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Joan Torres <joan.torres@suse.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_REMOTE_DISPLAY_H
|
||||||
|
#define __GDM_REMOTE_DISPLAY_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "gdm-display.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_REMOTE_DISPLAY (gdm_remote_display_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmRemoteDisplay, gdm_remote_display, GDM, REMOTE_DISPLAY, GdmDisplay)
|
||||||
|
|
||||||
|
GdmDisplay * gdm_remote_display_new (const char *remote_id);
|
||||||
|
|
||||||
|
char * gdm_remote_display_get_remote_id (GdmRemoteDisplay *self);
|
||||||
|
|
||||||
|
void gdm_remote_display_set_remote_id (GdmRemoteDisplay *self,
|
||||||
|
const char *remote_id);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_REMOTE_DISPLAY_H */
|
||||||
|
|
7
daemon/gdm-remote-display.xml
Normal file
7
daemon/gdm-remote-display.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node>
|
||||||
|
<interface name="org.gnome.DisplayManager.RemoteDisplay">
|
||||||
|
<property name="RemoteId" type="o" access="read"/>
|
||||||
|
<property name="SessionId" type="s" access="read"/>
|
||||||
|
</interface>
|
||||||
|
</node>
|
1089
daemon/gdm-server.c
Normal file
1089
daemon/gdm-server.c
Normal file
File diff suppressed because it is too large
Load diff
42
daemon/gdm-server.h
Normal file
42
daemon/gdm-server.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_SERVER_H
|
||||||
|
#define __GDM_SERVER_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SERVER (gdm_server_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmServer, gdm_server, GDM, SERVER, GObject);
|
||||||
|
|
||||||
|
GdmServer * gdm_server_new (const char *display_id,
|
||||||
|
const char *seat_id,
|
||||||
|
const char *auth_file,
|
||||||
|
gboolean initial);
|
||||||
|
gboolean gdm_server_start (GdmServer *server);
|
||||||
|
gboolean gdm_server_stop (GdmServer *server);
|
||||||
|
char * gdm_server_get_display_device (GdmServer *server);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_SERVER_H */
|
334
daemon/gdm-session-auditor.c
Normal file
334
daemon/gdm-session-auditor.c
Normal file
|
@ -0,0 +1,334 @@
|
||||||
|
/* gdm-session-auditor.c - Object for auditing session login/logout
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, 2008 Sun Microsystems, Inc.
|
||||||
|
* Copyright (C) 2005, 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Brian A. Cameron <Brian.Cameron@sun.com>
|
||||||
|
* Gary Winiger <Gary.Winiger@sun.com>
|
||||||
|
* Ray Strode <rstrode@redhat.com>
|
||||||
|
* Steve Grubb <sgrubb@redhat.com>
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include "gdm-session-auditor.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
typedef struct _GdmSessionAuditorPrivate
|
||||||
|
{
|
||||||
|
char *username;
|
||||||
|
char *hostname;
|
||||||
|
char *display_device;
|
||||||
|
} GdmSessionAuditorPrivate;
|
||||||
|
|
||||||
|
static void gdm_session_auditor_finalize (GObject *object);
|
||||||
|
static void gdm_session_auditor_class_install_properties (GdmSessionAuditorClass *
|
||||||
|
auditor_class);
|
||||||
|
|
||||||
|
static void gdm_session_auditor_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
static void gdm_session_auditor_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0 = 0,
|
||||||
|
PROP_USERNAME,
|
||||||
|
PROP_HOSTNAME,
|
||||||
|
PROP_DISPLAY_DEVICE
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (GdmSessionAuditor, gdm_session_auditor, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_class_init (GdmSessionAuditorClass *auditor_class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (auditor_class);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_session_auditor_finalize;
|
||||||
|
|
||||||
|
gdm_session_auditor_class_install_properties (auditor_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_class_install_properties (GdmSessionAuditorClass *auditor_class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
GParamSpec *param_spec;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (auditor_class);
|
||||||
|
object_class->set_property = gdm_session_auditor_set_property;
|
||||||
|
object_class->get_property = gdm_session_auditor_get_property;
|
||||||
|
|
||||||
|
param_spec = g_param_spec_string ("username", _("Username"),
|
||||||
|
_("The username"),
|
||||||
|
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||||
|
g_object_class_install_property (object_class, PROP_USERNAME, param_spec);
|
||||||
|
|
||||||
|
param_spec = g_param_spec_string ("hostname", _("Hostname"),
|
||||||
|
_("The hostname"),
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||||
|
g_object_class_install_property (object_class, PROP_HOSTNAME, param_spec);
|
||||||
|
|
||||||
|
param_spec = g_param_spec_string ("display-device", _("Display Device"),
|
||||||
|
_("The display device"),
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||||
|
g_object_class_install_property (object_class, PROP_DISPLAY_DEVICE, param_spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_init (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmSessionAuditor *auditor;
|
||||||
|
GdmSessionAuditorPrivate *priv;
|
||||||
|
GObjectClass *parent_class;
|
||||||
|
|
||||||
|
auditor = GDM_SESSION_AUDITOR (object);
|
||||||
|
priv = gdm_session_auditor_get_instance_private (auditor);
|
||||||
|
|
||||||
|
g_free (priv->username);
|
||||||
|
g_free (priv->hostname);
|
||||||
|
g_free (priv->display_device);
|
||||||
|
|
||||||
|
parent_class = G_OBJECT_CLASS (gdm_session_auditor_parent_class);
|
||||||
|
|
||||||
|
if (parent_class->finalize != NULL) {
|
||||||
|
parent_class->finalize (object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_auditor_set_username (GdmSessionAuditor *auditor,
|
||||||
|
const char *username)
|
||||||
|
{
|
||||||
|
GdmSessionAuditorPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
priv = gdm_session_auditor_get_instance_private (auditor);
|
||||||
|
|
||||||
|
if (username == priv->username) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((username == NULL || priv->username == NULL) ||
|
||||||
|
strcmp (username, priv->username) != 0) {
|
||||||
|
priv->username = g_strdup (username);
|
||||||
|
g_object_notify (G_OBJECT (auditor), "username");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_set_hostname (GdmSessionAuditor *auditor,
|
||||||
|
const char *hostname)
|
||||||
|
{
|
||||||
|
GdmSessionAuditorPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
priv = gdm_session_auditor_get_instance_private (auditor);
|
||||||
|
priv->hostname = g_strdup (hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_set_display_device (GdmSessionAuditor *auditor,
|
||||||
|
const char *display_device)
|
||||||
|
{
|
||||||
|
GdmSessionAuditorPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
priv = gdm_session_auditor_get_instance_private (auditor);
|
||||||
|
priv->display_device = g_strdup (display_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
gdm_session_auditor_get_username (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionAuditorPrivate *priv;
|
||||||
|
|
||||||
|
priv = gdm_session_auditor_get_instance_private (auditor);
|
||||||
|
return g_strdup (priv->username);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
gdm_session_auditor_get_hostname (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionAuditorPrivate *priv;
|
||||||
|
|
||||||
|
priv = gdm_session_auditor_get_instance_private (auditor);
|
||||||
|
return g_strdup (priv->hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
gdm_session_auditor_get_display_device (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionAuditorPrivate *priv;
|
||||||
|
|
||||||
|
priv = gdm_session_auditor_get_instance_private (auditor);
|
||||||
|
return g_strdup (priv->display_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSessionAuditor *auditor;
|
||||||
|
|
||||||
|
auditor = GDM_SESSION_AUDITOR (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_USERNAME:
|
||||||
|
gdm_session_auditor_set_username (auditor, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_HOSTNAME:
|
||||||
|
gdm_session_auditor_set_hostname (auditor, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DISPLAY_DEVICE:
|
||||||
|
gdm_session_auditor_set_display_device (auditor, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_auditor_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSessionAuditor *auditor;
|
||||||
|
|
||||||
|
auditor = GDM_SESSION_AUDITOR (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_USERNAME:
|
||||||
|
g_value_take_string (value, gdm_session_auditor_get_username (auditor));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_HOSTNAME:
|
||||||
|
g_value_take_string (value, gdm_session_auditor_get_hostname (auditor));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_DISPLAY_DEVICE:
|
||||||
|
g_value_take_string (value, gdm_session_auditor_get_display_device (auditor));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmSessionAuditor *
|
||||||
|
gdm_session_auditor_new (const char *hostname,
|
||||||
|
const char *display_device)
|
||||||
|
{
|
||||||
|
GdmSessionAuditor *auditor;
|
||||||
|
|
||||||
|
auditor = g_object_new (GDM_TYPE_SESSION_AUDITOR,
|
||||||
|
"hostname", hostname,
|
||||||
|
"display-device", display_device,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return auditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_auditor_report_password_changed (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
if (GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_password_changed != NULL) {
|
||||||
|
GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_password_changed (auditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_auditor_report_password_change_failure (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
if (GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_password_change_failure != NULL) {
|
||||||
|
GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_password_change_failure (auditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_auditor_report_user_accredited (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
if (GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_user_accredited != NULL) {
|
||||||
|
GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_user_accredited (auditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_auditor_report_login (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
if (GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_login != NULL) {
|
||||||
|
GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_login (auditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_auditor_report_login_failure (GdmSessionAuditor *auditor,
|
||||||
|
int error_code,
|
||||||
|
const char *error_message)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
if (GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_login_failure != NULL) {
|
||||||
|
GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_login_failure (auditor, error_code, error_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_auditor_report_logout (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_AUDITOR (auditor));
|
||||||
|
|
||||||
|
if (GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_logout != NULL) {
|
||||||
|
GDM_SESSION_AUDITOR_GET_CLASS (auditor)->report_logout (auditor);
|
||||||
|
}
|
||||||
|
}
|
65
daemon/gdm-session-auditor.h
Normal file
65
daemon/gdm-session-auditor.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/* gdm-session-auditor.h - Object for auditing session login/logout
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, 2008 Sun Microsystems, Inc.
|
||||||
|
* Copyright (C) 2005, 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Brian A. Cameron <Brian.Cameron@sun.com>
|
||||||
|
* Gary Winiger <Gary.Winiger@sun.com>
|
||||||
|
* Ray Strode <rstrode@redhat.com>
|
||||||
|
* Steve Grubb <sgrubb@redhat.com>
|
||||||
|
*/
|
||||||
|
#ifndef GDM_SESSION_AUDITOR_H
|
||||||
|
#define GDM_SESSION_AUDITOR_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SESSION_AUDITOR (gdm_session_auditor_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (GdmSessionAuditor, gdm_session_auditor, GDM, SESSION_AUDITOR, GObject)
|
||||||
|
|
||||||
|
struct _GdmSessionAuditorClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
void (* report_password_changed) (GdmSessionAuditor *auditor);
|
||||||
|
void (* report_password_change_failure) (GdmSessionAuditor *auditor);
|
||||||
|
void (* report_user_accredited) (GdmSessionAuditor *auditor);
|
||||||
|
void (* report_login) (GdmSessionAuditor *auditor);
|
||||||
|
void (* report_login_failure) (GdmSessionAuditor *auditor,
|
||||||
|
int error_code,
|
||||||
|
const char *error_message);
|
||||||
|
void (* report_logout) (GdmSessionAuditor *auditor);
|
||||||
|
};
|
||||||
|
|
||||||
|
GdmSessionAuditor *gdm_session_auditor_new (const char *hostname,
|
||||||
|
const char *display_device);
|
||||||
|
void gdm_session_auditor_set_username (GdmSessionAuditor *auditor,
|
||||||
|
const char *username);
|
||||||
|
void gdm_session_auditor_report_password_changed (GdmSessionAuditor *auditor);
|
||||||
|
void gdm_session_auditor_report_password_change_failure (GdmSessionAuditor *auditor);
|
||||||
|
void gdm_session_auditor_report_user_accredited (GdmSessionAuditor *auditor);
|
||||||
|
void gdm_session_auditor_report_login (GdmSessionAuditor *auditor);
|
||||||
|
void gdm_session_auditor_report_login_failure (GdmSessionAuditor *auditor,
|
||||||
|
int error_code,
|
||||||
|
const char *error_message);
|
||||||
|
void gdm_session_auditor_report_logout (GdmSessionAuditor *auditor);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* GDM_SESSION_AUDITOR_H */
|
42
daemon/gdm-session-enum-types.c.in
Normal file
42
daemon/gdm-session-enum-types.c.in
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*** BEGIN file-header ***/
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
/*** END file-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-production ***/
|
||||||
|
#include "@filename@"
|
||||||
|
/* enumerations from "@filename@" */
|
||||||
|
/*** END file-production ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-header ***/
|
||||||
|
GType @enum_name@_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GType
|
||||||
|
@enum_name@_get_type (void)
|
||||||
|
{
|
||||||
|
static GType etype = 0;
|
||||||
|
|
||||||
|
if (G_UNLIKELY(etype == 0)) {
|
||||||
|
static const G@Type@Value values[] = {
|
||||||
|
/*** END value-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-production ***/
|
||||||
|
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
|
||||||
|
/*** END value-production ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-tail ***/
|
||||||
|
{ 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return etype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** END value-tail ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-tail ***/
|
||||||
|
/**/
|
||||||
|
/*** END file-tail ***/
|
24
daemon/gdm-session-enum-types.h.in
Normal file
24
daemon/gdm-session-enum-types.h.in
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*** BEGIN file-header ***/
|
||||||
|
#ifndef GDM_SESSION_ENUM_TYPES_H
|
||||||
|
#define GDM_SESSION_ENUM_TYPES_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
/*** END file-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-production ***/
|
||||||
|
|
||||||
|
/* enumerations from "@filename@" */
|
||||||
|
/*** END file-production ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-header ***/
|
||||||
|
GType @enum_name@_get_type (void) G_GNUC_CONST;
|
||||||
|
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
|
||||||
|
/*** END value-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-tail ***/
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* GDM_SESSION_ENUM_TYPES_H */
|
||||||
|
/*** END file-tail ***/
|
161
daemon/gdm-session-linux-auditor.c
Normal file
161
daemon/gdm-session-linux-auditor.c
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, 2008 Sun Microsystems, Inc.
|
||||||
|
* Copyright (C) 2005, 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Brian A. Cameron <Brian.Cameron@sun.com>
|
||||||
|
* Gary Winiger <Gary.Winiger@sun.com>
|
||||||
|
* Ray Strode <rstrode@redhat.com>
|
||||||
|
* Steve Grubb <sgrubb@redhat.com>
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include "gdm-session-linux-auditor.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <libaudit.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
|
||||||
|
struct _GdmSessionLinuxAuditor
|
||||||
|
{
|
||||||
|
GdmSessionAuditor parent;
|
||||||
|
int audit_fd;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_session_linux_auditor_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmSessionLinuxAuditor, gdm_session_linux_auditor, GDM_TYPE_SESSION_AUDITOR)
|
||||||
|
|
||||||
|
static void
|
||||||
|
log_user_message (GdmSessionAuditor *auditor,
|
||||||
|
gint type,
|
||||||
|
gint result)
|
||||||
|
{
|
||||||
|
GdmSessionLinuxAuditor *linux_auditor;
|
||||||
|
char buf[512];
|
||||||
|
g_autofree char *username = NULL;
|
||||||
|
g_autofree char *hostname = NULL;
|
||||||
|
g_autofree char *display_device = NULL;
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
|
linux_auditor = GDM_SESSION_LINUX_AUDITOR (auditor);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (auditor), "username", &username, NULL);
|
||||||
|
g_object_get (G_OBJECT (auditor), "hostname", &hostname, NULL);
|
||||||
|
g_object_get (G_OBJECT (auditor), "display-device", &display_device, NULL);
|
||||||
|
|
||||||
|
if (username != NULL) {
|
||||||
|
gdm_get_pwent_for_name (username, &pw);
|
||||||
|
} else {
|
||||||
|
username = g_strdup ("unknown");
|
||||||
|
pw = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pw != NULL) {
|
||||||
|
g_snprintf (buf, sizeof (buf), "uid=%d", pw->pw_uid);
|
||||||
|
audit_log_user_message (linux_auditor->audit_fd, type,
|
||||||
|
buf, hostname, NULL, display_device,
|
||||||
|
result);
|
||||||
|
} else {
|
||||||
|
g_snprintf (buf, sizeof (buf), "acct=%s", username);
|
||||||
|
audit_log_user_message (linux_auditor->audit_fd, type,
|
||||||
|
buf, hostname, NULL, display_device,
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_linux_auditor_report_login (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
log_user_message (auditor, AUDIT_USER_LOGIN, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_linux_auditor_report_login_failure (GdmSessionAuditor *auditor,
|
||||||
|
int pam_error_code,
|
||||||
|
const char *pam_error_string)
|
||||||
|
{
|
||||||
|
log_user_message (auditor, AUDIT_USER_LOGIN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_linux_auditor_report_logout (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
log_user_message (auditor, AUDIT_USER_LOGOUT, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_linux_auditor_class_init (GdmSessionLinuxAuditorClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
GdmSessionAuditorClass *auditor_class;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (klass);
|
||||||
|
auditor_class = GDM_SESSION_AUDITOR_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_session_linux_auditor_finalize;
|
||||||
|
|
||||||
|
auditor_class->report_login = gdm_session_linux_auditor_report_login;
|
||||||
|
auditor_class->report_login_failure = gdm_session_linux_auditor_report_login_failure;
|
||||||
|
auditor_class->report_logout = gdm_session_linux_auditor_report_logout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_linux_auditor_init (GdmSessionLinuxAuditor *auditor)
|
||||||
|
{
|
||||||
|
auditor->audit_fd = audit_open ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_linux_auditor_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmSessionLinuxAuditor *linux_auditor;
|
||||||
|
GObjectClass *parent_class;
|
||||||
|
|
||||||
|
linux_auditor = GDM_SESSION_LINUX_AUDITOR (object);
|
||||||
|
|
||||||
|
close (linux_auditor->audit_fd);
|
||||||
|
|
||||||
|
parent_class = G_OBJECT_CLASS (gdm_session_linux_auditor_parent_class);
|
||||||
|
if (parent_class->finalize != NULL) {
|
||||||
|
parent_class->finalize (object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GdmSessionAuditor *
|
||||||
|
gdm_session_linux_auditor_new (const char *hostname,
|
||||||
|
const char *display_device)
|
||||||
|
{
|
||||||
|
GObject *auditor;
|
||||||
|
|
||||||
|
auditor = g_object_new (GDM_TYPE_SESSION_LINUX_AUDITOR,
|
||||||
|
"hostname", hostname,
|
||||||
|
"display-device", display_device,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GDM_SESSION_AUDITOR (auditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
43
daemon/gdm-session-linux-auditor.h
Normal file
43
daemon/gdm-session-linux-auditor.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* gdm-linux-session-auditor.h - Object for linux auditing of session login/logout
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, 2008 Sun Microsystems, Inc.
|
||||||
|
* Copyright (C) 2005, 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Brian A. Cameron <Brian.Cameron@sun.com>
|
||||||
|
* Gary Winiger <Gary.Winiger@sun.com>
|
||||||
|
* Ray Strode <rstrode@redhat.com>
|
||||||
|
* Steve Grubb <sgrubb@redhat.com>
|
||||||
|
*/
|
||||||
|
#ifndef GDM_SESSION_LINUX_AUDITOR_H
|
||||||
|
#define GDM_SESSION_LINUX_AUDITOR_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-session-auditor.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SESSION_LINUX_AUDITOR (gdm_session_linux_auditor_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSessionLinuxAuditor, gdm_session_linux_auditor, GDM, SESSION_LINUX_AUDITOR, GdmSessionAuditor)
|
||||||
|
|
||||||
|
GdmSessionAuditor *gdm_session_linux_auditor_new (const char *hostname,
|
||||||
|
const char *display_device);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* GDM_SESSION_LINUX_AUDITOR_H */
|
308
daemon/gdm-session-record.c
Normal file
308
daemon/gdm-session-record.c
Normal file
|
@ -0,0 +1,308 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_UTMPX_H)
|
||||||
|
#include <utmpx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_UTMP_H)
|
||||||
|
#include <utmp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include "gdm-session-record.h"
|
||||||
|
|
||||||
|
#ifndef GDM_BAD_SESSION_RECORDS_FILE
|
||||||
|
#define GDM_BAD_SESSION_RECORDS_FILE "/var/log/btmp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(GDM_NEW_SESSION_RECORDS_FILE)
|
||||||
|
# if defined(WTMPX_FILE)
|
||||||
|
# define GDM_NEW_SESSION_RECORDS_FILE WTMPX_FILE
|
||||||
|
# elif defined(_PATH_WTMPX)
|
||||||
|
# define GDM_NEW_SESSION_RECORDS_FILE _PATH_WTMPX
|
||||||
|
# elif defined(WTMPX_FILENAME)
|
||||||
|
# define GDM_NEW_SESSION_RECORDS_FILE WTMPX_FILENAME
|
||||||
|
# elif defined(WTMP_FILE)
|
||||||
|
# define GDM_NEW_SESSION_RECORDS_FILE WTMP_FILE
|
||||||
|
# elif defined(_PATH_WTMP) /* BSD systems */
|
||||||
|
# define GDM_NEW_SESSION_RECORDS_FILE _PATH_WTMP
|
||||||
|
# else
|
||||||
|
# define GDM_NEW_SESSION_RECORDS_FILE "/var/log/wtmp"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
record_set_username (UTMP *u,
|
||||||
|
const char *username)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_UT_UT_USER)
|
||||||
|
memccpy (u->ut_user, username, '\0', sizeof (u->ut_user));
|
||||||
|
g_debug ("using ut_user %.*s",
|
||||||
|
(int) sizeof (u->ut_user),
|
||||||
|
u->ut_user);
|
||||||
|
#elif defined(HAVE_UT_UT_NAME)
|
||||||
|
memccpy (u->ut_name, username, '\0', sizeof (u->ut_name));
|
||||||
|
g_debug ("using ut_name %.*s",
|
||||||
|
(int) sizeof (u->ut_name),
|
||||||
|
u->ut_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
record_set_timestamp (UTMP *u)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_UT_UT_TV)
|
||||||
|
gint64 now;
|
||||||
|
|
||||||
|
/* Set time in TV format */
|
||||||
|
now = g_get_real_time();
|
||||||
|
u->ut_tv.tv_sec = now / G_USEC_PER_SEC;
|
||||||
|
u->ut_tv.tv_usec = now % G_USEC_PER_SEC;
|
||||||
|
g_debug ("using ut_tv time %ld",
|
||||||
|
(glong) u->ut_tv.tv_sec);
|
||||||
|
#elif defined(HAVE_UT_UT_TIME)
|
||||||
|
/* Set time in time format */
|
||||||
|
time (&u->ut_time);
|
||||||
|
g_debug ("using ut_time %ld",
|
||||||
|
(glong) u->ut_time);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
record_set_pid (UTMP *u,
|
||||||
|
GPid pid)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_UT_UT_PID)
|
||||||
|
/* Set pid */
|
||||||
|
if (pid != 0) {
|
||||||
|
u->ut_pid = pid;
|
||||||
|
}
|
||||||
|
g_debug ("using ut_pid %d", (int) u->ut_pid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
record_set_host (UTMP *u,
|
||||||
|
const char *x11_display_name,
|
||||||
|
const char *host_name)
|
||||||
|
{
|
||||||
|
g_autofree char *hostname = NULL;
|
||||||
|
|
||||||
|
#if defined(HAVE_UT_UT_HOST)
|
||||||
|
/*
|
||||||
|
* Set ut_host to hostname:$DISPLAY if remote, otherwise set
|
||||||
|
* to $DISPLAY
|
||||||
|
*/
|
||||||
|
if (host_name != NULL
|
||||||
|
&& x11_display_name != NULL
|
||||||
|
&& g_str_has_prefix (x11_display_name, ":")) {
|
||||||
|
hostname = g_strdup_printf ("%s%s", host_name, x11_display_name);
|
||||||
|
} else {
|
||||||
|
hostname = g_strdup (x11_display_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostname != NULL) {
|
||||||
|
memccpy (u->ut_host, hostname, '\0', sizeof (u->ut_host));
|
||||||
|
g_debug ("using ut_host %.*s", (int) sizeof (u->ut_host), u->ut_host);
|
||||||
|
#ifdef HAVE_UT_UT_SYSLEN
|
||||||
|
u->ut_syslen = MIN (strlen (hostname), sizeof (u->ut_host));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
record_set_line (UTMP *u,
|
||||||
|
const char *display_device,
|
||||||
|
const char *x11_display_name)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set ut_line to the device name associated with this display
|
||||||
|
* but remove the "/dev/" prefix if there is one. Otherwise, if it
|
||||||
|
* seems like the display device is a seat id, just use it wholesale.
|
||||||
|
* If there's no device at all, but $DISPLAY is set, just fall back to
|
||||||
|
* using that.
|
||||||
|
*/
|
||||||
|
if (display_device != NULL && g_str_has_prefix (display_device, "/dev/")) {
|
||||||
|
memccpy (u->ut_line,
|
||||||
|
display_device + strlen ("/dev/"),
|
||||||
|
'\0',
|
||||||
|
sizeof (u->ut_line));
|
||||||
|
} else if (display_device != NULL && g_str_has_prefix (display_device, "seat")) {
|
||||||
|
memccpy (u->ut_line,
|
||||||
|
display_device,
|
||||||
|
'\0',
|
||||||
|
sizeof (u->ut_line));
|
||||||
|
} else if (x11_display_name != NULL) {
|
||||||
|
memccpy (u->ut_line,
|
||||||
|
x11_display_name,
|
||||||
|
'\0',
|
||||||
|
sizeof (u->ut_line));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("using ut_line %.*s", (int) sizeof (u->ut_line), u->ut_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_record_login (GPid session_pid,
|
||||||
|
const char *user_name,
|
||||||
|
const char *host_name,
|
||||||
|
const char *x11_display_name,
|
||||||
|
const char *display_device)
|
||||||
|
{
|
||||||
|
UTMP session_record = { 0 };
|
||||||
|
|
||||||
|
if (x11_display_name == NULL)
|
||||||
|
x11_display_name = display_device;
|
||||||
|
|
||||||
|
record_set_username (&session_record, user_name);
|
||||||
|
|
||||||
|
g_debug ("Writing login record");
|
||||||
|
|
||||||
|
#if defined(HAVE_UT_UT_TYPE)
|
||||||
|
session_record.ut_type = USER_PROCESS;
|
||||||
|
g_debug ("using ut_type USER_PROCESS");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
record_set_timestamp (&session_record);
|
||||||
|
record_set_pid (&session_record, session_pid);
|
||||||
|
record_set_host (&session_record, x11_display_name, host_name);
|
||||||
|
record_set_line (&session_record, display_device, x11_display_name);
|
||||||
|
|
||||||
|
/* Handle wtmp */
|
||||||
|
g_debug ("Writing wtmp session record to " GDM_NEW_SESSION_RECORDS_FILE);
|
||||||
|
#if defined(HAVE_UPDWTMPX)
|
||||||
|
updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
|
||||||
|
#elif defined(HAVE_UPDWTMP)
|
||||||
|
updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
|
||||||
|
#elif defined(HAVE_LOGWTMP) && defined(HAVE_UT_UT_HOST)
|
||||||
|
#if defined(HAVE_UT_UT_USER)
|
||||||
|
logwtmp (session_record.ut_line, session_record.ut_user, session_record.ut_host);
|
||||||
|
#elif defined(HAVE_UT_UT_NAME)
|
||||||
|
logwtmp (session_record.ut_line, session_record.ut_name, session_record.ut_host);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Handle utmp */
|
||||||
|
#if defined(HAVE_GETUTXENT)
|
||||||
|
g_debug ("Adding or updating utmp record for login");
|
||||||
|
setutxent();
|
||||||
|
pututxline (&session_record);
|
||||||
|
endutxent();
|
||||||
|
#elif defined(HAVE_LOGIN)
|
||||||
|
login (&session_record);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_record_logout (GPid session_pid,
|
||||||
|
const char *user_name,
|
||||||
|
const char *host_name,
|
||||||
|
const char *x11_display_name,
|
||||||
|
const char *display_device)
|
||||||
|
{
|
||||||
|
UTMP session_record = { 0 };
|
||||||
|
|
||||||
|
if (x11_display_name == NULL)
|
||||||
|
x11_display_name = display_device;
|
||||||
|
|
||||||
|
g_debug ("Writing logout record");
|
||||||
|
|
||||||
|
#if defined(HAVE_UT_UT_TYPE)
|
||||||
|
session_record.ut_type = DEAD_PROCESS;
|
||||||
|
g_debug ("using ut_type DEAD_PROCESS");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
record_set_timestamp (&session_record);
|
||||||
|
record_set_pid (&session_record, session_pid);
|
||||||
|
record_set_host (&session_record, x11_display_name, host_name);
|
||||||
|
record_set_line (&session_record, display_device, x11_display_name);
|
||||||
|
|
||||||
|
/* Handle wtmp */
|
||||||
|
g_debug ("Writing wtmp logout record to " GDM_NEW_SESSION_RECORDS_FILE);
|
||||||
|
#if defined(HAVE_UPDWTMPX)
|
||||||
|
updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
|
||||||
|
#elif defined (HAVE_UPDWTMP)
|
||||||
|
updwtmp (GDM_NEW_SESSION_RECORDS_FILE, &session_record);
|
||||||
|
#elif defined(HAVE_LOGWTMP)
|
||||||
|
logwtmp (session_record.ut_line, "", "");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Handle utmp */
|
||||||
|
#if defined(HAVE_GETUTXENT)
|
||||||
|
g_debug ("Adding or updating utmp record for logout");
|
||||||
|
setutxent();
|
||||||
|
pututxline (&session_record);
|
||||||
|
endutxent();
|
||||||
|
#elif defined(HAVE_LOGOUT)
|
||||||
|
logout (session_record.ut_line);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_record_failed (GPid session_pid,
|
||||||
|
const char *user_name,
|
||||||
|
const char *host_name,
|
||||||
|
const char *x11_display_name,
|
||||||
|
const char *display_device)
|
||||||
|
{
|
||||||
|
UTMP session_record = { 0 };
|
||||||
|
|
||||||
|
if (x11_display_name == NULL)
|
||||||
|
x11_display_name = display_device;
|
||||||
|
|
||||||
|
record_set_username (&session_record, user_name);
|
||||||
|
|
||||||
|
g_debug ("Writing failed session attempt record");
|
||||||
|
|
||||||
|
#if defined(HAVE_UT_UT_TYPE)
|
||||||
|
session_record.ut_type = USER_PROCESS;
|
||||||
|
g_debug ("using ut_type USER_PROCESS");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
record_set_timestamp (&session_record);
|
||||||
|
record_set_pid (&session_record, session_pid);
|
||||||
|
record_set_host (&session_record, x11_display_name, host_name);
|
||||||
|
record_set_line (&session_record, display_device, x11_display_name);
|
||||||
|
|
||||||
|
#if defined(HAVE_UPDWTMPX) || defined(HAVE_UPDWTMP)
|
||||||
|
/* Handle btmp */
|
||||||
|
g_debug ("Writing btmp failed session attempt record to "
|
||||||
|
GDM_BAD_SESSION_RECORDS_FILE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_UPDWTMPX)
|
||||||
|
updwtmpx (GDM_BAD_SESSION_RECORDS_FILE, &session_record);
|
||||||
|
#elif defined(HAVE_UPDWTMP)
|
||||||
|
updwtmp(GDM_BAD_SESSION_RECORDS_FILE, &session_record);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
50
daemon/gdm-session-record.h
Normal file
50
daemon/gdm-session-record.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_SESSION_RECORD_H
|
||||||
|
#define __GDM_SESSION_RECORD_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_record_login (GPid session_pid,
|
||||||
|
const char *user_name,
|
||||||
|
const char *host_name,
|
||||||
|
const char *x11_display_name,
|
||||||
|
const char *display_device);
|
||||||
|
void
|
||||||
|
gdm_session_record_logout (GPid session_pid,
|
||||||
|
const char *user_name,
|
||||||
|
const char *host_name,
|
||||||
|
const char *x11_display_name,
|
||||||
|
const char *display_device);
|
||||||
|
void
|
||||||
|
gdm_session_record_failed (GPid session_pid,
|
||||||
|
const char *user_name,
|
||||||
|
const char *host_name,
|
||||||
|
const char *x11_display_name,
|
||||||
|
const char *display_device);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* GDM_SESSION_RECORD_H */
|
410
daemon/gdm-session-settings.c
Normal file
410
daemon/gdm-session-settings.c
Normal file
|
@ -0,0 +1,410 @@
|
||||||
|
/* gdm-session-settings.c - Loads session and language from ~/.dmrc
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Ray Strode <rstrode@redhat.com>
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include "gdm-session-settings.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include <act/act-user-manager.h>
|
||||||
|
|
||||||
|
struct _GdmSessionSettings
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
ActUserManager *user_manager;
|
||||||
|
ActUser *user;
|
||||||
|
char *session_name;
|
||||||
|
char *session_type;
|
||||||
|
char *language_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_session_settings_finalize (GObject *object);
|
||||||
|
static void gdm_session_settings_class_install_properties (GdmSessionSettingsClass *
|
||||||
|
settings_class);
|
||||||
|
|
||||||
|
static void gdm_session_settings_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
static void gdm_session_settings_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0 = 0,
|
||||||
|
PROP_SESSION_NAME,
|
||||||
|
PROP_SESSION_TYPE,
|
||||||
|
PROP_LANGUAGE_NAME,
|
||||||
|
PROP_IS_LOADED
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmSessionSettings, gdm_session_settings, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_settings_class_init (GdmSessionSettingsClass *settings_class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (settings_class);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_session_settings_finalize;
|
||||||
|
|
||||||
|
gdm_session_settings_class_install_properties (settings_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_settings_class_install_properties (GdmSessionSettingsClass *settings_class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
GParamSpec *param_spec;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (settings_class);
|
||||||
|
object_class->set_property = gdm_session_settings_set_property;
|
||||||
|
object_class->get_property = gdm_session_settings_get_property;
|
||||||
|
|
||||||
|
param_spec = g_param_spec_string ("session-name", "Session Name",
|
||||||
|
"The name of the session",
|
||||||
|
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||||
|
g_object_class_install_property (object_class, PROP_SESSION_NAME, param_spec);
|
||||||
|
|
||||||
|
param_spec = g_param_spec_string ("session-type", "Session Type",
|
||||||
|
"The type of the session",
|
||||||
|
NULL, G_PARAM_READWRITE);
|
||||||
|
g_object_class_install_property (object_class, PROP_SESSION_TYPE, param_spec);
|
||||||
|
|
||||||
|
param_spec = g_param_spec_string ("language-name", "Language Name",
|
||||||
|
"The name of the language",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||||
|
g_object_class_install_property (object_class, PROP_LANGUAGE_NAME, param_spec);
|
||||||
|
|
||||||
|
param_spec = g_param_spec_boolean ("is-loaded", NULL, NULL,
|
||||||
|
FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||||
|
g_object_class_install_property (object_class, PROP_IS_LOADED, param_spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_settings_init (GdmSessionSettings *settings)
|
||||||
|
{
|
||||||
|
settings->user_manager = act_user_manager_get_default ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_settings_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmSessionSettings *settings;
|
||||||
|
GObjectClass *parent_class;
|
||||||
|
|
||||||
|
settings = GDM_SESSION_SETTINGS (object);
|
||||||
|
|
||||||
|
if (settings->user != NULL) {
|
||||||
|
g_object_unref (settings->user);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (settings->session_name);
|
||||||
|
g_free (settings->language_name);
|
||||||
|
|
||||||
|
parent_class = G_OBJECT_CLASS (gdm_session_settings_parent_class);
|
||||||
|
|
||||||
|
if (parent_class->finalize != NULL) {
|
||||||
|
parent_class->finalize (object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_settings_set_language_name (GdmSessionSettings *settings,
|
||||||
|
const char *language_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
|
||||||
|
|
||||||
|
if (settings->language_name == NULL ||
|
||||||
|
strcmp (settings->language_name, language_name) != 0) {
|
||||||
|
settings->language_name = g_strdup (language_name);
|
||||||
|
g_object_notify (G_OBJECT (settings), "language-name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_settings_set_session_name (GdmSessionSettings *settings,
|
||||||
|
const char *session_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
|
||||||
|
|
||||||
|
if (settings->session_name == NULL ||
|
||||||
|
strcmp (settings->session_name, session_name) != 0) {
|
||||||
|
settings->session_name = g_strdup (session_name);
|
||||||
|
g_object_notify (G_OBJECT (settings), "session-name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_settings_set_session_type (GdmSessionSettings *settings,
|
||||||
|
const char *session_type)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
|
||||||
|
|
||||||
|
if (settings->session_type == NULL ||
|
||||||
|
g_strcmp0 (settings->session_type, session_type) != 0) {
|
||||||
|
settings->session_type = g_strdup (session_type);
|
||||||
|
g_object_notify (G_OBJECT (settings), "session-type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_session_settings_get_language_name (GdmSessionSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
|
||||||
|
return g_strdup (settings->language_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_session_settings_get_session_name (GdmSessionSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
|
||||||
|
return g_strdup (settings->session_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
gdm_session_settings_get_session_type (GdmSessionSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
|
||||||
|
return g_strdup (settings->session_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_settings_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSessionSettings *settings;
|
||||||
|
|
||||||
|
settings = GDM_SESSION_SETTINGS (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_LANGUAGE_NAME:
|
||||||
|
gdm_session_settings_set_language_name (settings, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SESSION_NAME:
|
||||||
|
gdm_session_settings_set_session_name (settings, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SESSION_TYPE:
|
||||||
|
gdm_session_settings_set_session_type (settings, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_settings_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSessionSettings *settings;
|
||||||
|
|
||||||
|
settings = GDM_SESSION_SETTINGS (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_SESSION_NAME:
|
||||||
|
g_value_set_string (value, settings->session_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_SESSION_TYPE:
|
||||||
|
g_value_set_string (value, settings->session_type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_LANGUAGE_NAME:
|
||||||
|
g_value_set_string (value, settings->language_name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_IS_LOADED:
|
||||||
|
g_value_set_boolean (value, gdm_session_settings_is_loaded (settings));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmSessionSettings *
|
||||||
|
gdm_session_settings_new (void)
|
||||||
|
{
|
||||||
|
GdmSessionSettings *settings;
|
||||||
|
|
||||||
|
settings = g_object_new (GDM_TYPE_SESSION_SETTINGS,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_session_settings_is_loaded (GdmSessionSettings *settings)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), FALSE);
|
||||||
|
|
||||||
|
if (settings->user == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return act_user_is_loaded (settings->user);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_settings_from_user (GdmSessionSettings *settings)
|
||||||
|
{
|
||||||
|
const char *session_name;
|
||||||
|
const char *session_type;
|
||||||
|
const char *language_name;
|
||||||
|
|
||||||
|
if (!act_user_is_loaded (settings->user)) {
|
||||||
|
g_warning ("GdmSessionSettings: trying to load user settings from unloaded user");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load settings even if the user doesn't have saved state, as they could have been
|
||||||
|
* configured in AccountsService by the administrator */
|
||||||
|
session_type = act_user_get_session_type (settings->user);
|
||||||
|
session_name = act_user_get_session (settings->user);
|
||||||
|
|
||||||
|
g_debug ("GdmSessionSettings: saved session is %s (type %s)", session_name, session_type);
|
||||||
|
|
||||||
|
if (session_type != NULL && session_type[0] != '\0') {
|
||||||
|
gdm_session_settings_set_session_type (settings, session_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session_name != NULL && session_name[0] != '\0') {
|
||||||
|
gdm_session_settings_set_session_name (settings, session_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
language_name = act_user_get_language (settings->user);
|
||||||
|
|
||||||
|
g_debug ("GdmSessionSettings: saved language is %s", language_name);
|
||||||
|
if (language_name != NULL && language_name[0] != '\0') {
|
||||||
|
gdm_session_settings_set_language_name (settings, language_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (settings), "is-loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_user_is_loaded_changed (ActUser *user,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
GdmSessionSettings *settings)
|
||||||
|
{
|
||||||
|
if (act_user_is_loaded (settings->user)) {
|
||||||
|
load_settings_from_user (settings);
|
||||||
|
g_signal_handlers_disconnect_by_func (G_OBJECT (settings->user),
|
||||||
|
G_CALLBACK (on_user_is_loaded_changed),
|
||||||
|
settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_session_settings_load (GdmSessionSettings *settings,
|
||||||
|
const char *username)
|
||||||
|
{
|
||||||
|
g_autoptr(ActUser) old_user = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), FALSE);
|
||||||
|
g_return_val_if_fail (username != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (!gdm_session_settings_is_loaded (settings), FALSE);
|
||||||
|
|
||||||
|
old_user = g_steal_pointer (&settings->user);
|
||||||
|
if (old_user != NULL) {
|
||||||
|
g_signal_handlers_disconnect_by_func (G_OBJECT (old_user),
|
||||||
|
G_CALLBACK (on_user_is_loaded_changed),
|
||||||
|
settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
settings->user = act_user_manager_get_user (settings->user_manager,
|
||||||
|
username);
|
||||||
|
|
||||||
|
if (!act_user_is_loaded (settings->user)) {
|
||||||
|
g_signal_connect (settings->user,
|
||||||
|
"notify::is-loaded",
|
||||||
|
G_CALLBACK (on_user_is_loaded_changed),
|
||||||
|
settings);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_settings_from_user (settings);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gdm_session_settings_save (GdmSessionSettings *settings,
|
||||||
|
const char *username)
|
||||||
|
{
|
||||||
|
g_autoptr(ActUser) user = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), FALSE);
|
||||||
|
g_return_val_if_fail (username != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (gdm_session_settings_is_loaded (settings), FALSE);
|
||||||
|
|
||||||
|
user = act_user_manager_get_user (settings->user_manager,
|
||||||
|
username);
|
||||||
|
|
||||||
|
|
||||||
|
if (!act_user_is_loaded (user)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->session_name != NULL) {
|
||||||
|
act_user_set_session (user, settings->session_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->session_type != NULL) {
|
||||||
|
act_user_set_session_type (user, settings->session_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->language_name != NULL) {
|
||||||
|
act_user_set_language (user, settings->language_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!act_user_is_local_account (user)) {
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
act_user_manager_cache_user (settings->user_manager, username, &error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("GdmSessionSettings: Could not locally cache remote user: %s", error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
51
daemon/gdm-session-settings.h
Normal file
51
daemon/gdm-session-settings.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/* gdm-session-settings.h - Object for auditing session login/logout
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Ray Strode <rstrode@redhat.com>
|
||||||
|
*/
|
||||||
|
#ifndef GDM_SESSION_SETTINGS_H
|
||||||
|
#define GDM_SESSION_SETTINGS_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SESSION_SETTINGS (gdm_session_settings_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSessionSettings, gdm_session_settings, GDM, SESSION_SETTINGS, GObject)
|
||||||
|
|
||||||
|
GdmSessionSettings *gdm_session_settings_new (void);
|
||||||
|
|
||||||
|
gboolean gdm_session_settings_load (GdmSessionSettings *settings,
|
||||||
|
const char *username);
|
||||||
|
gboolean gdm_session_settings_save (GdmSessionSettings *settings,
|
||||||
|
const char *username);
|
||||||
|
gboolean gdm_session_settings_is_loaded (GdmSessionSettings *settings);
|
||||||
|
char *gdm_session_settings_get_language_name (GdmSessionSettings *settings);
|
||||||
|
char *gdm_session_settings_get_session_name (GdmSessionSettings *settings);
|
||||||
|
char *gdm_session_settings_get_session_type (GdmSessionSettings *settings);
|
||||||
|
void gdm_session_settings_set_language_name (GdmSessionSettings *settings,
|
||||||
|
const char *language_name);
|
||||||
|
void gdm_session_settings_set_session_name (GdmSessionSettings *settings,
|
||||||
|
const char *session_name);
|
||||||
|
void gdm_session_settings_set_session_type (GdmSessionSettings *settings,
|
||||||
|
const char *session_type);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* GDM_SESSION_SETTINGS_H */
|
390
daemon/gdm-session-solaris-auditor.c
Normal file
390
daemon/gdm-session-solaris-auditor.c
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, 2008 Sun Microsystems, Inc.
|
||||||
|
* Copyright (C) 2005, 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Brian A. Cameron <Brian.Cameron@sun.com>
|
||||||
|
* Gary Winiger <Gary.Winiger@sun.com>
|
||||||
|
* Ray Strode <rstrode@redhat.com>
|
||||||
|
* Steve Grubb <sgrubb@redhat.com>
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
#include "gdm-session-solaris-auditor.h"
|
||||||
|
#include "gdm-common.h"
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <security/pam_appl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <bsm/adt.h>
|
||||||
|
#include <bsm/adt_event.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
struct _GdmSessionSolarisAuditor
|
||||||
|
{
|
||||||
|
GdmSessionAuditor parent;
|
||||||
|
|
||||||
|
adt_session_data_t *audit_session_handle;
|
||||||
|
|
||||||
|
guint password_change_initiated : 1;
|
||||||
|
guint password_changed : 1;
|
||||||
|
guint user_accredited : 1;
|
||||||
|
|
||||||
|
/* cached values to prevent repeated calls
|
||||||
|
* to getpwnam
|
||||||
|
*/
|
||||||
|
char *username;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gdm_session_solaris_auditor_finalize (GObject *object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmSessionSolarisAuditor, gdm_session_solaris_auditor, GDM_TYPE_SESSION_AUDITOR)
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_report_password_changed (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionSolarisAuditor *solaris_auditor;
|
||||||
|
|
||||||
|
solaris_auditor = GDM_SESSION_SOLARIS_AUDITOR (auditor);
|
||||||
|
solaris_auditor->password_change_initiated = TRUE;
|
||||||
|
solaris_auditor->password_changed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_report_password_change_failure (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionSolarisAuditor *solaris_auditor;
|
||||||
|
|
||||||
|
solaris_auditor = GDM_SESSION_SOLARIS_AUDITOR (auditor);
|
||||||
|
solaris_auditor->password_change_initiated = TRUE;
|
||||||
|
solaris_auditor->password_changed = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_report_user_accredited (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionSolarisAuditor *solaris_auditor;
|
||||||
|
|
||||||
|
solaris_auditor = GDM_SESSION_SOLARIS_AUDITOR (auditor);
|
||||||
|
solaris_auditor->user_accredited = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_report_login (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionSolarisAuditor *solaris_auditor;
|
||||||
|
adt_session_data_t *adt_ah; /* Audit session handle */
|
||||||
|
adt_event_data_t *event; /* Event to generate */
|
||||||
|
|
||||||
|
solaris_auditor = GDM_SESSION_SOLARIS_AUDITOR (auditor);
|
||||||
|
|
||||||
|
g_return_if_fail (solaris_auditor->username != NULL);
|
||||||
|
|
||||||
|
adt_ah = NULL;
|
||||||
|
if (adt_start_session (&adt_ah, NULL, ADT_USE_PROC_DATA) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_start_session (ADT_login): %m");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adt_set_user (adt_ah, solaris_auditor->uid,
|
||||||
|
solaris_auditor->gid, solaris_auditor->uid,
|
||||||
|
solaris_auditor->gid, NULL, ADT_USER) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_set_user (ADT_login, %s): %m",
|
||||||
|
solaris_auditor->username);
|
||||||
|
}
|
||||||
|
|
||||||
|
event = adt_alloc_event (adt_ah, ADT_login);
|
||||||
|
if (event == NULL) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT, "adt_alloc_event (ADT_login): %m");
|
||||||
|
} else if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_put_event (ADT_login, ADT_SUCCESS): %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (solaris_auditor->password_changed) {
|
||||||
|
|
||||||
|
g_assert (solaris_auditor->password_change_initiated);
|
||||||
|
|
||||||
|
/* Also audit password change */
|
||||||
|
adt_free_event (event);
|
||||||
|
event = adt_alloc_event (adt_ah, ADT_passwd);
|
||||||
|
if (event == NULL) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_alloc_event (ADT_passwd): %m");
|
||||||
|
} else if (adt_put_event (event, ADT_SUCCESS,
|
||||||
|
ADT_SUCCESS) != 0) {
|
||||||
|
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_put_event (ADT_passwd, ADT_SUCCESS): %m");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adt_free_event (event);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
solaris_auditor->audit_session_handle = adt_ah;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_report_login_failure (GdmSessionAuditor *auditor,
|
||||||
|
int pam_error_code,
|
||||||
|
const char *pam_error_string)
|
||||||
|
{
|
||||||
|
GdmSessionSolarisAuditor *solaris_auditor;
|
||||||
|
char *hostname;
|
||||||
|
char *display_device;
|
||||||
|
adt_session_data_t *ah; /* Audit session handle */
|
||||||
|
adt_event_data_t *event; /* Event to generate */
|
||||||
|
adt_termid_t *tid; /* Terminal ID for failures */
|
||||||
|
|
||||||
|
solaris_auditor = GDM_SESSION_SOLARIS_AUDITOR (auditor);
|
||||||
|
g_object_get (G_OBJECT (auditor),
|
||||||
|
"hostname", &hostname,
|
||||||
|
"display-device", &display_device, NULL);
|
||||||
|
|
||||||
|
if (solaris_auditor->user_accredited) {
|
||||||
|
if (adt_start_session (&ah, NULL, ADT_USE_PROC_DATA) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_start_session (ADT_login, ADT_FAILURE): %m");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (adt_start_session (&ah, NULL, 0) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_start_session (ADT_login, ADT_FAILURE): %m");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If display is on console or VT */
|
||||||
|
if (hostname != NULL && hostname[0] != '\0') {
|
||||||
|
/* Login from a remote host */
|
||||||
|
if (adt_load_hostname (hostname, &tid) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_loadhostname (%s): %m", hostname);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* login from the local host */
|
||||||
|
if (adt_load_ttyname (display_device, &tid) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_loadhostname (localhost): %m");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adt_set_user (ah,
|
||||||
|
solaris_auditor->username != NULL ? solaris_auditor->uid : ADT_NO_ATTRIB,
|
||||||
|
solaris_auditor->username != NULL ? solaris_auditor->gid : ADT_NO_ATTRIB,
|
||||||
|
solaris_auditor->username != NULL ? solaris_auditor->uid : ADT_NO_ATTRIB,
|
||||||
|
solaris_auditor->username != NULL ? solaris_auditor->gid : ADT_NO_ATTRIB,
|
||||||
|
tid, ADT_NEW) != 0) {
|
||||||
|
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_set_user (%s): %m",
|
||||||
|
solaris_auditor->username != NULL ? solaris_auditor->username : "ADT_NO_ATTRIB");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event = adt_alloc_event (ah, ADT_login);
|
||||||
|
|
||||||
|
if (event == NULL) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_alloc_event (ADT_login, ADT_FAILURE): %m");
|
||||||
|
goto done;
|
||||||
|
} else if (adt_put_event (event, ADT_FAILURE,
|
||||||
|
ADT_FAIL_PAM + pam_error_code) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_put_event (ADT_login (ADT_FAIL, %s): %m",
|
||||||
|
pam_error_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (solaris_auditor->password_change_initiated) {
|
||||||
|
/* Also audit password change */
|
||||||
|
adt_free_event (event);
|
||||||
|
|
||||||
|
event = adt_alloc_event (ah, ADT_passwd);
|
||||||
|
if (event == NULL) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_alloc_event (ADT_passwd): %m");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (solaris_auditor->password_changed) {
|
||||||
|
if (adt_put_event (event, ADT_SUCCESS,
|
||||||
|
ADT_SUCCESS) != 0) {
|
||||||
|
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_put_event (ADT_passwd, ADT_SUCCESS): "
|
||||||
|
"%m");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (adt_put_event (event, ADT_FAILURE,
|
||||||
|
ADT_FAIL_PAM + pam_error_code) != 0) {
|
||||||
|
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_put_event (ADT_passwd, ADT_FAILURE): "
|
||||||
|
"%m");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
adt_free_event (event);
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* Reset process audit state. this process is being reused.*/
|
||||||
|
if ((adt_set_user (ah, ADT_NO_AUDIT, ADT_NO_AUDIT, ADT_NO_AUDIT,
|
||||||
|
ADT_NO_AUDIT, NULL, ADT_NEW) != 0) ||
|
||||||
|
(adt_set_proc (ah) != 0)) {
|
||||||
|
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_put_event (ADT_login (ADT_FAILURE reset, %m)");
|
||||||
|
}
|
||||||
|
(void) adt_end_session (ah);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
g_free (hostname);
|
||||||
|
g_free (display_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_report_logout (GdmSessionAuditor *auditor)
|
||||||
|
{
|
||||||
|
GdmSessionSolarisAuditor *solaris_auditor;
|
||||||
|
adt_session_data_t *adt_ah; /* Audit session handle */
|
||||||
|
adt_event_data_t *event; /* Event to generate */
|
||||||
|
|
||||||
|
solaris_auditor = GDM_SESSION_SOLARIS_AUDITOR (auditor);
|
||||||
|
|
||||||
|
adt_ah = solaris_auditor->audit_session_handle;
|
||||||
|
|
||||||
|
event = adt_alloc_event (adt_ah, ADT_logout);
|
||||||
|
if (event == NULL) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_alloc_event (ADT_logout): %m");
|
||||||
|
} else if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_put_event (ADT_logout, ADT_SUCCESS): %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
adt_free_event (event);
|
||||||
|
|
||||||
|
/* Reset process audit state. this process is being reused. */
|
||||||
|
if ((adt_set_user (adt_ah, ADT_NO_AUDIT, ADT_NO_AUDIT, ADT_NO_AUDIT,
|
||||||
|
ADT_NO_AUDIT, NULL, ADT_NEW) != 0) ||
|
||||||
|
(adt_set_proc (adt_ah) != 0)) {
|
||||||
|
syslog (LOG_AUTH | LOG_ALERT,
|
||||||
|
"adt_set_proc (ADT_logout reset): %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) adt_end_session (adt_ah);
|
||||||
|
solaris_auditor->audit_session_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_class_init (GdmSessionSolarisAuditorClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
GdmSessionAuditorClass *auditor_class;
|
||||||
|
|
||||||
|
object_class = G_OBJECT_CLASS (klass);
|
||||||
|
auditor_class = GDM_SESSION_AUDITOR_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdm_session_solaris_auditor_finalize;
|
||||||
|
|
||||||
|
auditor_class->report_password_changed = gdm_session_solaris_auditor_report_password_changed;
|
||||||
|
auditor_class->report_password_change_failure = gdm_session_solaris_auditor_report_password_change_failure;
|
||||||
|
auditor_class->report_user_accredited = gdm_session_solaris_auditor_report_user_accredited;
|
||||||
|
auditor_class->report_login = gdm_session_solaris_auditor_report_login;
|
||||||
|
auditor_class->report_login_failure = gdm_session_solaris_auditor_report_login_failure;
|
||||||
|
auditor_class->report_logout = gdm_session_solaris_auditor_report_logout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_username_set (GdmSessionSolarisAuditor *auditor)
|
||||||
|
{
|
||||||
|
char *username;
|
||||||
|
struct passwd *passwd_entry = NULL;
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (auditor), "username", &username, NULL);
|
||||||
|
|
||||||
|
if (username != NULL) {
|
||||||
|
gdm_get_pwent_for_name (username, &passwd_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passwd_entry != NULL) {
|
||||||
|
auditor->uid = passwd_entry->pw_uid;
|
||||||
|
auditor->gid = passwd_entry->pw_gid;
|
||||||
|
auditor->username = g_strdup (passwd_entry->pw_name);
|
||||||
|
} else {
|
||||||
|
g_free (auditor->username);
|
||||||
|
auditor->username = NULL;
|
||||||
|
auditor->uid = (uid_t) -1;
|
||||||
|
auditor->gid = (gid_t) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (username);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_init (GdmSessionSolarisAuditor *auditor)
|
||||||
|
{
|
||||||
|
g_signal_connect (G_OBJECT (auditor), "notify::username",
|
||||||
|
G_CALLBACK (on_username_set), NULL);
|
||||||
|
|
||||||
|
auditor->uid = (uid_t) -1;
|
||||||
|
auditor->gid = (gid_t) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_solaris_auditor_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmSessionSolarisAuditor *solaris_auditor;
|
||||||
|
GObjectClass *parent_class;
|
||||||
|
|
||||||
|
solaris_auditor = GDM_SESSION_SOLARIS_AUDITOR (object);
|
||||||
|
|
||||||
|
g_free (solaris_auditor->username);
|
||||||
|
solaris_auditor->username = NULL;
|
||||||
|
|
||||||
|
parent_class = G_OBJECT_CLASS (gdm_session_solaris_auditor_parent_class);
|
||||||
|
|
||||||
|
if (parent_class->finalize != NULL) {
|
||||||
|
parent_class->finalize (object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmSessionAuditor *
|
||||||
|
gdm_session_solaris_auditor_new (const char *hostname,
|
||||||
|
const char *display_device)
|
||||||
|
{
|
||||||
|
GObject *auditor;
|
||||||
|
|
||||||
|
auditor = g_object_new (GDM_TYPE_SESSION_SOLARIS_AUDITOR,
|
||||||
|
"hostname", hostname,
|
||||||
|
"display-device", display_device,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GDM_SESSION_AUDITOR (auditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
42
daemon/gdm-session-solaris-auditor.h
Normal file
42
daemon/gdm-session-solaris-auditor.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* gdm-solaris-session-auditor.h - Object for solaris auditing of session login/logout
|
||||||
|
*
|
||||||
|
* Copyright (C) 2004, 2008 Sun Microsystems, Inc.
|
||||||
|
* Copyright (C) 2005, 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*
|
||||||
|
* Written by: Brian A. Cameron <Brian.Cameron@sun.com>
|
||||||
|
* Gary Winiger <Gary.Winiger@sun.com>
|
||||||
|
* Ray Strode <rstrode@redhat.com>
|
||||||
|
* Steve Grubb <sgrubb@redhat.com>
|
||||||
|
*/
|
||||||
|
#ifndef GDM_SESSION_SOLARIS_AUDITOR_H
|
||||||
|
#define GDM_SESSION_SOLARIS_AUDITOR_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-session-auditor.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SESSION_SOLARIS_AUDITOR (gdm_session_solaris_auditor_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSessionSolarisAuditor, gdm_session_solaris_auditor, GDM, SESSION_SOLARIS_AUDITOR, GdmSessionAuditor)
|
||||||
|
|
||||||
|
GdmSessionAuditor *gdm_session_solaris_auditor_new (const char *hostname,
|
||||||
|
const char *display_device);
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* GDM_SESSION_SOLARIS_AUDITOR_H */
|
57
daemon/gdm-session-worker-common.c
Normal file
57
daemon/gdm-session-worker-common.c
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
|
||||||
|
* Copyright (C) 2012 Jasper St. Pierre <jstpierre@mecheye.net>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
#include "gdm-session-worker-common.h"
|
||||||
|
|
||||||
|
static const GDBusErrorEntry gdm_session_worker_error_entries[] = {
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_GENERIC , "org.gnome.DisplayManager.SessionWorker.Error.Generic", },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_WITH_SESSION_COMMAND , "org.gnome.DisplayManager.SessionWorker.Error.WithSessionCommand" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_FORKING , "org.gnome.DisplayManager.SessionWorker.Error.Forking" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_OPENING_MESSAGE_PIPE , "org.gnome.DisplayManager.SessionWorker.Error.OpeningMessagePipe" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_COMMUNICATING , "org.gnome.DisplayManager.SessionWorker.Error.Communicating" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_WORKER_DIED , "org.gnome.DisplayManager.SessionWorker.Error.WorkerDied" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE , "org.gnome.DisplayManager.SessionWorker.Error.ServiceUnavailable" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_AUTHENTICATING , "org.gnome.DisplayManager.SessionWorker.Error.Authenticating" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_AUTHORIZING , "org.gnome.DisplayManager.SessionWorker.Error.Authorizing" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_OPENING_LOG_FILE , "org.gnome.DisplayManager.SessionWorker.Error.OpeningLogFile" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_OPENING_SESSION , "org.gnome.DisplayManager.SessionWorker.Error.OpeningSession" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS , "org.gnome.DisplayManager.SessionWorker.Error.GivingCredentials" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_WRONG_STATE , "org.gnome.DisplayManager.SessionWorker.Error.WrongState" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_OUTSTANDING_REQUEST , "org.gnome.DisplayManager.SessionWorker.Error.OutstandingRequest" },
|
||||||
|
{ GDM_SESSION_WORKER_ERROR_IN_REAUTH_SESSION , "org.gnome.DisplayManager.SessionWorker.Error.InReauthSession" }
|
||||||
|
};
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
gdm_session_worker_error_quark (void)
|
||||||
|
{
|
||||||
|
static volatile gsize error_quark = 0;
|
||||||
|
|
||||||
|
g_dbus_error_register_error_domain ("gdm-session-worker-error-quark",
|
||||||
|
&error_quark,
|
||||||
|
gdm_session_worker_error_entries,
|
||||||
|
G_N_ELEMENTS (gdm_session_worker_error_entries));
|
||||||
|
|
||||||
|
return (GQuark) error_quark;
|
||||||
|
}
|
50
daemon/gdm-session-worker-common.h
Normal file
50
daemon/gdm-session-worker-common.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
|
||||||
|
* Copyright (C) 2012 Jasper St. Pierre <jstpierre@mecheye.net>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_SESSION_WORKER_COMMON_H
|
||||||
|
#define __GDM_SESSION_WORKER_COMMON_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#define GDM_SESSION_WORKER_ERROR (gdm_session_worker_error_quark ())
|
||||||
|
|
||||||
|
GQuark gdm_session_worker_error_quark (void);
|
||||||
|
|
||||||
|
typedef enum _GdmSessionWorkerError {
|
||||||
|
GDM_SESSION_WORKER_ERROR_GENERIC = 0,
|
||||||
|
GDM_SESSION_WORKER_ERROR_WITH_SESSION_COMMAND,
|
||||||
|
GDM_SESSION_WORKER_ERROR_FORKING,
|
||||||
|
GDM_SESSION_WORKER_ERROR_OPENING_MESSAGE_PIPE,
|
||||||
|
GDM_SESSION_WORKER_ERROR_COMMUNICATING,
|
||||||
|
GDM_SESSION_WORKER_ERROR_WORKER_DIED,
|
||||||
|
GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE,
|
||||||
|
GDM_SESSION_WORKER_ERROR_TOO_MANY_RETRIES,
|
||||||
|
GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
|
||||||
|
GDM_SESSION_WORKER_ERROR_AUTHORIZING,
|
||||||
|
GDM_SESSION_WORKER_ERROR_OPENING_LOG_FILE,
|
||||||
|
GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
|
||||||
|
GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS,
|
||||||
|
GDM_SESSION_WORKER_ERROR_WRONG_STATE,
|
||||||
|
GDM_SESSION_WORKER_ERROR_OUTSTANDING_REQUEST,
|
||||||
|
GDM_SESSION_WORKER_ERROR_IN_REAUTH_SESSION,
|
||||||
|
} GdmSessionWorkerError;
|
||||||
|
|
||||||
|
#endif /* GDM_SESSION_WORKER_COMMON_H */
|
42
daemon/gdm-session-worker-enum-types.c.in
Normal file
42
daemon/gdm-session-worker-enum-types.c.in
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*** BEGIN file-header ***/
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
/*** END file-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-production ***/
|
||||||
|
#include "@filename@"
|
||||||
|
/* enumerations from "@filename@" */
|
||||||
|
/*** END file-production ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-header ***/
|
||||||
|
GType @enum_name@_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GType
|
||||||
|
@enum_name@_get_type (void)
|
||||||
|
{
|
||||||
|
static GType etype = 0;
|
||||||
|
|
||||||
|
if (G_UNLIKELY(etype == 0)) {
|
||||||
|
static const G@Type@Value values[] = {
|
||||||
|
/*** END value-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-production ***/
|
||||||
|
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
|
||||||
|
/*** END value-production ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-tail ***/
|
||||||
|
{ 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||||
|
}
|
||||||
|
|
||||||
|
return etype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** END value-tail ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-tail ***/
|
||||||
|
/**/
|
||||||
|
/*** END file-tail ***/
|
24
daemon/gdm-session-worker-enum-types.h.in
Normal file
24
daemon/gdm-session-worker-enum-types.h.in
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/*** BEGIN file-header ***/
|
||||||
|
#ifndef GDM_SESSION_WORKER_ENUM_TYPES_H
|
||||||
|
#define GDM_SESSION_WORKER_ENUM_TYPES_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
/*** END file-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-production ***/
|
||||||
|
|
||||||
|
/* enumerations from "@filename@" */
|
||||||
|
/*** END file-production ***/
|
||||||
|
|
||||||
|
/*** BEGIN value-header ***/
|
||||||
|
GType @enum_name@_get_type (void) G_GNUC_CONST;
|
||||||
|
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
|
||||||
|
/*** END value-header ***/
|
||||||
|
|
||||||
|
/*** BEGIN file-tail ***/
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* GDM_SESSION_WORKER_ENUM_TYPES_H */
|
||||||
|
/*** END file-tail ***/
|
556
daemon/gdm-session-worker-job.c
Normal file
556
daemon/gdm-session-worker-job.c
Normal file
|
@ -0,0 +1,556 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#ifdef HAVE_SYS_PRCTL_H
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_SYSTEMD_JOURNAL
|
||||||
|
#include <systemd/sd-journal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
|
||||||
|
#include "gdm-session-worker-job.h"
|
||||||
|
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
struct _GdmSessionWorkerJob
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
char *command;
|
||||||
|
GPid pid;
|
||||||
|
gboolean for_reauth;
|
||||||
|
|
||||||
|
guint child_watch_id;
|
||||||
|
|
||||||
|
char *server_address;
|
||||||
|
char **environment;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_SERVER_ADDRESS,
|
||||||
|
PROP_ENVIRONMENT,
|
||||||
|
PROP_FOR_REAUTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
STARTED,
|
||||||
|
EXITED,
|
||||||
|
DIED,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals [LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GdmSessionWorkerJob, gdm_session_worker_job, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
session_worker_job_setup_journal_fds (void)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SYSTEMD_JOURNAL
|
||||||
|
if (sd_booted () > 0) {
|
||||||
|
const char *identifier = "gdm-session-worker";
|
||||||
|
int out, err;
|
||||||
|
|
||||||
|
out = sd_journal_stream_fd (identifier, LOG_INFO, FALSE);
|
||||||
|
if (out < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
err = sd_journal_stream_fd (identifier, LOG_WARNING, FALSE);
|
||||||
|
if (err < 0) {
|
||||||
|
close (out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VE_IGNORE_EINTR (dup2 (out, 1));
|
||||||
|
VE_IGNORE_EINTR (dup2 (err, 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
session_worker_job_child_setup (GdmSessionWorkerJob *session_worker_job)
|
||||||
|
{
|
||||||
|
sigset_t mask;
|
||||||
|
session_worker_job_setup_journal_fds ();
|
||||||
|
|
||||||
|
/* Terminate the process when the parent dies */
|
||||||
|
#ifdef HAVE_SYS_PRCTL_H
|
||||||
|
prctl (PR_SET_PDEATHSIG, SIGTERM);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Reset signal mask to default since it was altered by the
|
||||||
|
* manager process
|
||||||
|
*/
|
||||||
|
sigemptyset (&mask);
|
||||||
|
sigprocmask (SIG_SETMASK, &mask, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
session_worker_job_child_watch (GPid pid,
|
||||||
|
int status,
|
||||||
|
GdmSessionWorkerJob *job)
|
||||||
|
{
|
||||||
|
g_debug ("GdmSessionWorkerJob: child (pid:%d) done (%s:%d)",
|
||||||
|
(int) pid,
|
||||||
|
WIFEXITED (status) ? "status"
|
||||||
|
: WIFSIGNALED (status) ? "signal"
|
||||||
|
: "unknown",
|
||||||
|
WIFEXITED (status) ? WEXITSTATUS (status)
|
||||||
|
: WIFSIGNALED (status) ? WTERMSIG (status)
|
||||||
|
: -1);
|
||||||
|
|
||||||
|
g_spawn_close_pid (job->pid);
|
||||||
|
job->pid = -1;
|
||||||
|
|
||||||
|
if (WIFEXITED (status)) {
|
||||||
|
int code = WEXITSTATUS (status);
|
||||||
|
g_signal_emit (job, signals [EXITED], 0, code);
|
||||||
|
} else if (WIFSIGNALED (status)) {
|
||||||
|
int num = WTERMSIG (status);
|
||||||
|
g_signal_emit (job, signals [DIED], 0, num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
listify_hash (const char *key,
|
||||||
|
const char *value,
|
||||||
|
GPtrArray *env)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
value = "";
|
||||||
|
|
||||||
|
str = g_strdup_printf ("%s=%s", key, value);
|
||||||
|
g_ptr_array_add (env, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
copy_environment_to_hash (GdmSessionWorkerJob *job,
|
||||||
|
GHashTable *hash)
|
||||||
|
{
|
||||||
|
g_auto(GStrv) environment = NULL;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
if (job->environment != NULL) {
|
||||||
|
environment = g_strdupv (job->environment);
|
||||||
|
} else {
|
||||||
|
environment = g_get_environ ();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; environment[i]; i++) {
|
||||||
|
g_auto(GStrv) parts = NULL;
|
||||||
|
|
||||||
|
parts = g_strsplit (environment[i], "=", 2);
|
||||||
|
|
||||||
|
if (parts[0] != NULL && parts[1] != NULL) {
|
||||||
|
g_hash_table_insert (hash, g_strdup (parts[0]), g_strdup (parts[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GPtrArray *
|
||||||
|
get_job_arguments (GdmSessionWorkerJob *job,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
g_autoptr(GPtrArray) args = NULL;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_auto(GStrv) argv = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
args = NULL;
|
||||||
|
if (!g_shell_parse_argv (job->command, NULL, &argv, &error)) {
|
||||||
|
g_warning ("Could not parse command: %s", error->message);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
args = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
g_ptr_array_add (args, g_strdup (argv[0]));
|
||||||
|
g_ptr_array_add (args, g_strdup (name));
|
||||||
|
for (i = 1; argv[i] != NULL; i++) {
|
||||||
|
g_ptr_array_add (args, g_strdup (argv[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add (args, NULL);
|
||||||
|
|
||||||
|
return g_steal_pointer (&args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GPtrArray *
|
||||||
|
get_job_environment (GdmSessionWorkerJob *job)
|
||||||
|
{
|
||||||
|
g_autoptr(GPtrArray) env = NULL;
|
||||||
|
g_autoptr(GHashTable) hash = NULL;
|
||||||
|
|
||||||
|
env = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
|
||||||
|
/* create a hash table of current environment, then update keys has necessary */
|
||||||
|
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
copy_environment_to_hash (job, hash);
|
||||||
|
|
||||||
|
g_hash_table_insert (hash, g_strdup ("GDM_SESSION_DBUS_ADDRESS"), g_strdup (job->server_address));
|
||||||
|
|
||||||
|
if (job->for_reauth) {
|
||||||
|
g_hash_table_insert (hash, g_strdup ("GDM_SESSION_FOR_REAUTH"), g_strdup ("1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
|
||||||
|
|
||||||
|
g_ptr_array_add (env, NULL);
|
||||||
|
|
||||||
|
return g_steal_pointer (&env);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gdm_session_worker_job_spawn (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(GPtrArray) args = NULL;
|
||||||
|
g_autoptr(GPtrArray) env = NULL;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
g_debug ("GdmSessionWorkerJob: Running session_worker_job process: %s %s",
|
||||||
|
name != NULL? name : "", session_worker_job->command);
|
||||||
|
|
||||||
|
args = get_job_arguments (session_worker_job, name);
|
||||||
|
|
||||||
|
if (args == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
env = get_job_environment (session_worker_job);
|
||||||
|
|
||||||
|
ret = g_spawn_async_with_pipes (NULL,
|
||||||
|
(char **) args->pdata,
|
||||||
|
(char **)env->pdata,
|
||||||
|
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_FILE_AND_ARGV_ZERO,
|
||||||
|
(GSpawnChildSetupFunc)session_worker_job_child_setup,
|
||||||
|
session_worker_job,
|
||||||
|
&session_worker_job->pid,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (! ret) {
|
||||||
|
g_warning ("Could not start command '%s': %s",
|
||||||
|
session_worker_job->command,
|
||||||
|
error->message);
|
||||||
|
} else {
|
||||||
|
g_debug ("GdmSessionWorkerJob: : SessionWorkerJob on pid %d", (int)session_worker_job->pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
session_worker_job->child_watch_id = g_child_watch_add (session_worker_job->pid,
|
||||||
|
(GChildWatchFunc)session_worker_job_child_watch,
|
||||||
|
session_worker_job);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gdm_session_worker_job_start:
|
||||||
|
* @disp: Pointer to a GdmDisplay structure
|
||||||
|
*
|
||||||
|
* Starts a local X session_worker_job. Handles retries and fatal errors properly.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job), FALSE);
|
||||||
|
|
||||||
|
g_debug ("GdmSessionWorkerJob: Starting worker...");
|
||||||
|
|
||||||
|
res = gdm_session_worker_job_spawn (session_worker_job, name);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_session_worker_job_death (GdmSessionWorkerJob *session_worker_job)
|
||||||
|
{
|
||||||
|
int exit_status;
|
||||||
|
|
||||||
|
g_debug ("GdmSessionWorkerJob: Waiting on process %d", session_worker_job->pid);
|
||||||
|
exit_status = gdm_wait_on_and_disown_pid (session_worker_job->pid, 5);
|
||||||
|
|
||||||
|
if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
|
||||||
|
g_debug ("GdmSessionWorkerJob: Wait on child process failed");
|
||||||
|
} else {
|
||||||
|
/* exited normally */
|
||||||
|
}
|
||||||
|
|
||||||
|
g_spawn_close_pid (session_worker_job->pid);
|
||||||
|
session_worker_job->pid = -1;
|
||||||
|
|
||||||
|
g_debug ("GdmSessionWorkerJob: SessionWorkerJob died");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_worker_job_stop_now (GdmSessionWorkerJob *session_worker_job)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job));
|
||||||
|
|
||||||
|
if (session_worker_job->pid <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove watch source before we can wait on child */
|
||||||
|
g_clear_handle_id (&session_worker_job->child_watch_id, g_source_remove);
|
||||||
|
|
||||||
|
gdm_session_worker_job_stop (session_worker_job);
|
||||||
|
handle_session_worker_job_death (session_worker_job);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job));
|
||||||
|
|
||||||
|
if (session_worker_job->pid <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_debug ("GdmSessionWorkerJob: Stopping job pid:%d", session_worker_job->pid);
|
||||||
|
|
||||||
|
res = gdm_signal_pid (session_worker_job->pid, SIGTERM);
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
g_warning ("Unable to kill session worker process");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GPid
|
||||||
|
gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job), 0);
|
||||||
|
return session_worker_job->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_worker_job_set_server_address (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
const char *address)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job));
|
||||||
|
|
||||||
|
g_free (session_worker_job->server_address);
|
||||||
|
session_worker_job->server_address = g_strdup (address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_worker_job_set_for_reauth (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
gboolean for_reauth)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job));
|
||||||
|
|
||||||
|
session_worker_job->for_reauth = for_reauth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdm_session_worker_job_set_environment (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
const char * const *environment)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (session_worker_job));
|
||||||
|
|
||||||
|
session_worker_job->environment = g_strdupv ((char **) environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_worker_job_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdmSessionWorkerJob *session_worker_job;
|
||||||
|
|
||||||
|
g_return_if_fail (object != NULL);
|
||||||
|
g_return_if_fail (GDM_IS_SESSION_WORKER_JOB (object));
|
||||||
|
|
||||||
|
session_worker_job = GDM_SESSION_WORKER_JOB (object);
|
||||||
|
|
||||||
|
gdm_session_worker_job_stop (session_worker_job);
|
||||||
|
|
||||||
|
g_free (session_worker_job->command);
|
||||||
|
g_free (session_worker_job->server_address);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdm_session_worker_job_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_worker_job_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSessionWorkerJob *self;
|
||||||
|
|
||||||
|
self = GDM_SESSION_WORKER_JOB (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_SERVER_ADDRESS:
|
||||||
|
gdm_session_worker_job_set_server_address (self, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_FOR_REAUTH:
|
||||||
|
gdm_session_worker_job_set_for_reauth (self, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_ENVIRONMENT:
|
||||||
|
gdm_session_worker_job_set_environment (self, g_value_get_pointer (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_worker_job_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GdmSessionWorkerJob *self;
|
||||||
|
|
||||||
|
self = GDM_SESSION_WORKER_JOB (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_SERVER_ADDRESS:
|
||||||
|
g_value_set_string (value, self->server_address);
|
||||||
|
break;
|
||||||
|
case PROP_FOR_REAUTH:
|
||||||
|
g_value_set_boolean (value, self->for_reauth);
|
||||||
|
break;
|
||||||
|
case PROP_ENVIRONMENT:
|
||||||
|
g_value_set_pointer (value, self->environment);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_worker_job_init (GdmSessionWorkerJob *session_worker_job)
|
||||||
|
{
|
||||||
|
session_worker_job->pid = -1;
|
||||||
|
|
||||||
|
session_worker_job->command = g_strdup (LIBEXECDIR "/gdm-session-worker");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdm_session_worker_job_class_init (GdmSessionWorkerJobClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = gdm_session_worker_job_get_property;
|
||||||
|
object_class->set_property = gdm_session_worker_job_set_property;
|
||||||
|
object_class->finalize = gdm_session_worker_job_finalize;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_SERVER_ADDRESS,
|
||||||
|
g_param_spec_string ("server-address",
|
||||||
|
"server address",
|
||||||
|
"server address",
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_FOR_REAUTH,
|
||||||
|
g_param_spec_boolean ("for-reauth",
|
||||||
|
"for reauth",
|
||||||
|
"for reauth",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_ENVIRONMENT,
|
||||||
|
g_param_spec_pointer ("environment",
|
||||||
|
"environment",
|
||||||
|
"environment",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
signals [STARTED] =
|
||||||
|
g_signal_new ("started",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0);
|
||||||
|
signals [EXITED] =
|
||||||
|
g_signal_new ("exited",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__INT,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1,
|
||||||
|
G_TYPE_INT);
|
||||||
|
|
||||||
|
signals [DIED] =
|
||||||
|
g_signal_new ("died",
|
||||||
|
G_OBJECT_CLASS_TYPE (object_class),
|
||||||
|
G_SIGNAL_RUN_FIRST,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__INT,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
1,
|
||||||
|
G_TYPE_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
GdmSessionWorkerJob *
|
||||||
|
gdm_session_worker_job_new (void)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
|
||||||
|
object = g_object_new (GDM_TYPE_SESSION_WORKER_JOB,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GDM_SESSION_WORKER_JOB (object);
|
||||||
|
}
|
48
daemon/gdm-session-worker-job.h
Normal file
48
daemon/gdm-session-worker-job.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GDM_SESSION_WORKER_JOB_H
|
||||||
|
#define __GDM_SESSION_WORKER_JOB_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SESSION_WORKER_JOB (gdm_session_worker_job_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSessionWorkerJob, gdm_session_worker_job, GDM, SESSION_WORKER_JOB, GObject)
|
||||||
|
|
||||||
|
GdmSessionWorkerJob * gdm_session_worker_job_new (void);
|
||||||
|
void gdm_session_worker_job_set_server_address (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
const char *server_address);
|
||||||
|
void gdm_session_worker_job_set_for_reauth (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
gboolean for_reauth);
|
||||||
|
void gdm_session_worker_job_set_environment (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
const char * const *environment);
|
||||||
|
gboolean gdm_session_worker_job_start (GdmSessionWorkerJob *session_worker_job,
|
||||||
|
const char *name);
|
||||||
|
void gdm_session_worker_job_stop (GdmSessionWorkerJob *session_worker_job);
|
||||||
|
void gdm_session_worker_job_stop_now (GdmSessionWorkerJob *session_worker_job);
|
||||||
|
|
||||||
|
GPid gdm_session_worker_job_get_pid (GdmSessionWorkerJob *session_worker_job);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GDM_SESSION_WORKER_JOB_H */
|
3660
daemon/gdm-session-worker.c
Normal file
3660
daemon/gdm-session-worker.c
Normal file
File diff suppressed because it is too large
Load diff
49
daemon/gdm-session-worker.h
Normal file
49
daemon/gdm-session-worker.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_SESSION_WORKER_H
|
||||||
|
#define __GDM_SESSION_WORKER_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "gdm-session-worker-glue.h"
|
||||||
|
#include "gdm-session-worker-common.h"
|
||||||
|
#include "gdm-session-worker-enum-types.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SESSION_WORKER (gdm_session_worker_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSessionWorker, gdm_session_worker, GDM, SESSION_WORKER, GdmDBusWorkerSkeleton)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GDM_SESSION_WORKER_STATE_NONE = 0,
|
||||||
|
GDM_SESSION_WORKER_STATE_SETUP_COMPLETE,
|
||||||
|
GDM_SESSION_WORKER_STATE_AUTHENTICATED,
|
||||||
|
GDM_SESSION_WORKER_STATE_AUTHORIZED,
|
||||||
|
GDM_SESSION_WORKER_STATE_ACCREDITED,
|
||||||
|
GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED,
|
||||||
|
GDM_SESSION_WORKER_STATE_SESSION_OPENED,
|
||||||
|
GDM_SESSION_WORKER_STATE_SESSION_STARTED
|
||||||
|
} GdmSessionWorkerState;
|
||||||
|
|
||||||
|
GdmSessionWorker * gdm_session_worker_new (const char *server_address,
|
||||||
|
gboolean is_for_reauth) G_GNUC_MALLOC;
|
||||||
|
G_END_DECLS
|
||||||
|
#endif /* GDM_SESSION_WORKER_H */
|
94
daemon/gdm-session-worker.xml
Normal file
94
daemon/gdm-session-worker.xml
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node name="/org/gnome/DisplayManager/Worker">
|
||||||
|
<interface name="org.gnome.DisplayManager.Worker">
|
||||||
|
<method name="Authenticate" />
|
||||||
|
<method name="Authorize" />
|
||||||
|
<method name="EstablishCredentials" />
|
||||||
|
<method name="Open">
|
||||||
|
<arg name="session_id" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="SetLanguageName">
|
||||||
|
<arg name="language" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="SetSessionName">
|
||||||
|
<arg name="session_name" direction="in" type="s" />
|
||||||
|
</method>
|
||||||
|
<method name="SetSessionDisplayMode">
|
||||||
|
<arg name="mode" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="SetEnvironmentVariable">
|
||||||
|
<arg name="name" direction="in" type="s"/>
|
||||||
|
<arg name="value" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="StartProgram">
|
||||||
|
<arg name="command" direction="in" type="s"/>
|
||||||
|
<arg name="child_pid" direction="out" type="i"/>
|
||||||
|
</method>
|
||||||
|
<method name="Initialize">
|
||||||
|
<arg name="details" direction="in" type="a{sv}"/>
|
||||||
|
</method>
|
||||||
|
<method name="Setup">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="x11_display_name" direction="in" type="s"/>
|
||||||
|
<arg name="x11_authority_file" direction="in" type="s"/>
|
||||||
|
<arg name="display_device" direction="in" type="s"/>
|
||||||
|
<arg name="display_seat" direction="in" type="s"/>
|
||||||
|
<arg name="hostname" direction="in" type="s"/>
|
||||||
|
<arg name="display_is_local" direction="in" type="b"/>
|
||||||
|
<arg name="display_is_initial" direction="in" type="b"/>
|
||||||
|
</method>
|
||||||
|
<method name="SetupForUser">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="user_name" direction="in" type="s"/>
|
||||||
|
<arg name="x11_display_name" direction="in" type="s"/>
|
||||||
|
<arg name="x11_authority_file" direction="in" type="s"/>
|
||||||
|
<arg name="display_device" direction="in" type="s"/>
|
||||||
|
<arg name="display_seat" direction="in" type="s"/>
|
||||||
|
<arg name="hostname" direction="in" type="s"/>
|
||||||
|
<arg name="display_is_local" direction="in" type="b"/>
|
||||||
|
<arg name="display_is_initial" direction="in" type="b"/>
|
||||||
|
</method>
|
||||||
|
<method name="SetupForProgram">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="user_name" direction="in" type="s"/>
|
||||||
|
<arg name="x11_display_name" direction="in" type="s"/>
|
||||||
|
<arg name="x11_authority_file" direction="in" type="s"/>
|
||||||
|
<arg name="display_device" direction="in" type="s"/>
|
||||||
|
<arg name="display_seat" direction="in" type="s"/>
|
||||||
|
<arg name="hostname" direction="in" type="s"/>
|
||||||
|
<arg name="display_is_local" direction="in" type="b"/>
|
||||||
|
<arg name="display_is_initial" direction="in" type="b"/>
|
||||||
|
<arg name="log_file" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="StartReauthentication">
|
||||||
|
<arg name="pid_of_caller" direction="in" type="i"/>
|
||||||
|
<arg name="uid_of_caller" direction="in" type="i"/>
|
||||||
|
<arg name="address" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<signal name="SessionExited">
|
||||||
|
<arg name="service_name" type="s" />
|
||||||
|
<!-- This is a combination of exit code and exit
|
||||||
|
signal. Use macros in sys/wait.h to handle it. -->
|
||||||
|
<arg name="status" type="i" />
|
||||||
|
</signal>
|
||||||
|
<signal name="SavedLanguageNameRead">
|
||||||
|
<arg name="language_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="SavedSessionNameRead">
|
||||||
|
<arg name="session_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="SavedSessionTypeRead">
|
||||||
|
<arg name="session_type" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="UsernameChanged">
|
||||||
|
<arg name="new_username" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="Reauthenticated">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="pid_of_caller" type="i"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="CancelPendingQuery">
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
</node>
|
4505
daemon/gdm-session.c
Normal file
4505
daemon/gdm-session.c
Normal file
File diff suppressed because it is too large
Load diff
139
daemon/gdm-session.h
Normal file
139
daemon/gdm-session.h
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GDM_SESSION_H
|
||||||
|
#define __GDM_SESSION_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define GDM_TYPE_SESSION (gdm_session_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (GdmSession, gdm_session, GDM, SESSION, GObject)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GDM_SESSION_VERIFICATION_MODE_LOGIN,
|
||||||
|
GDM_SESSION_VERIFICATION_MODE_CHOOSER,
|
||||||
|
GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE
|
||||||
|
} GdmSessionVerificationMode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* We reuse the existing display server, e.g. X server
|
||||||
|
* in "classic" mode from the greeter for the first seat. */
|
||||||
|
GDM_SESSION_DISPLAY_MODE_REUSE_VT,
|
||||||
|
|
||||||
|
/* Doesn't know anything about VTs. Tries to set DRM
|
||||||
|
* master and will throw a tantrum if something bad
|
||||||
|
* happens. e.g. weston-launch or mutter-launch. */
|
||||||
|
GDM_SESSION_DISPLAY_MODE_NEW_VT,
|
||||||
|
|
||||||
|
/* Uses logind sessions to manage itself. We need to set an
|
||||||
|
* XDG_VTNR and it will switch to the correct VT on startup.
|
||||||
|
* e.g. mutter-wayland with logind integration, X server with
|
||||||
|
* logind integration. */
|
||||||
|
GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED,
|
||||||
|
} GdmSessionDisplayMode;
|
||||||
|
|
||||||
|
GdmSessionDisplayMode gdm_session_display_mode_from_string (const char *str);
|
||||||
|
const char * gdm_session_display_mode_to_string (GdmSessionDisplayMode mode);
|
||||||
|
|
||||||
|
GdmSession *gdm_session_new (GdmSessionVerificationMode verification_mode,
|
||||||
|
uid_t allowed_user,
|
||||||
|
const char *display_name,
|
||||||
|
const char *display_hostname,
|
||||||
|
const char *display_device,
|
||||||
|
const char *display_seat_id,
|
||||||
|
const char *display_x11_authority_file,
|
||||||
|
gboolean display_is_local,
|
||||||
|
const char * const *environment);
|
||||||
|
uid_t gdm_session_get_allowed_user (GdmSession *session);
|
||||||
|
void gdm_session_start_reauthentication (GdmSession *session,
|
||||||
|
GPid pid_of_caller,
|
||||||
|
uid_t uid_of_caller);
|
||||||
|
|
||||||
|
const char *gdm_session_get_server_address (GdmSession *session);
|
||||||
|
const char *gdm_session_get_username (GdmSession *session);
|
||||||
|
const char *gdm_session_get_display_device (GdmSession *session);
|
||||||
|
const char *gdm_session_get_display_seat_id (GdmSession *session);
|
||||||
|
const char *gdm_session_get_session_id (GdmSession *session);
|
||||||
|
gboolean gdm_session_bypasses_xsession (GdmSession *session);
|
||||||
|
gboolean gdm_session_session_registers (GdmSession *session);
|
||||||
|
GdmSessionDisplayMode gdm_session_get_display_mode (GdmSession *session);
|
||||||
|
gboolean gdm_session_start_conversation (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_stop_conversation (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
const char *gdm_session_get_conversation_session_id (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_setup (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_setup_for_user (GdmSession *session,
|
||||||
|
const char *service_name,
|
||||||
|
const char *username);
|
||||||
|
void gdm_session_setup_for_program (GdmSession *session,
|
||||||
|
const char *service_name,
|
||||||
|
const char *username,
|
||||||
|
const char *log_file);
|
||||||
|
void gdm_session_set_environment_variable (GdmSession *session,
|
||||||
|
const char *key,
|
||||||
|
const char *value);
|
||||||
|
void gdm_session_send_environment (GdmSession *self,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_reset (GdmSession *session);
|
||||||
|
void gdm_session_cancel (GdmSession *session);
|
||||||
|
void gdm_session_authenticate (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_authorize (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_accredit (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_open_session (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_start_session (GdmSession *session,
|
||||||
|
const char *service_name);
|
||||||
|
void gdm_session_close (GdmSession *session);
|
||||||
|
|
||||||
|
void gdm_session_answer_query (GdmSession *session,
|
||||||
|
const char *service_name,
|
||||||
|
const char *text);
|
||||||
|
void gdm_session_report_error (GdmSession *session,
|
||||||
|
const char *service_name,
|
||||||
|
GDBusError code,
|
||||||
|
const char *message);
|
||||||
|
void gdm_session_select_program (GdmSession *session,
|
||||||
|
const char *command_line);
|
||||||
|
void gdm_session_select_session (GdmSession *session,
|
||||||
|
const char *session_name);
|
||||||
|
void gdm_session_select_user (GdmSession *session,
|
||||||
|
const char *username);
|
||||||
|
void gdm_session_set_timed_login_details (GdmSession *session,
|
||||||
|
const char *username,
|
||||||
|
int delay);
|
||||||
|
gboolean gdm_session_client_is_connected (GdmSession *session);
|
||||||
|
gboolean gdm_session_is_running (GdmSession *session);
|
||||||
|
gboolean gdm_session_is_frozen (GdmSession *session);
|
||||||
|
GPid gdm_session_get_pid (GdmSession *session);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* GDM_SESSION_H */
|
173
daemon/gdm-session.xml
Normal file
173
daemon/gdm-session.xml
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node name="/org/gnome/DisplayManager/Session">
|
||||||
|
<!-- methods are called by the session worker,
|
||||||
|
signals are emitted by the main daemon -->
|
||||||
|
<interface name="org.gnome.DisplayManager.WorkerManager">
|
||||||
|
<method name="Hello" />
|
||||||
|
<method name="InfoQuery">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="query" direction="in" type="s"/>
|
||||||
|
<arg name="answer" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="SecretInfoQuery">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="query" direction="in" type="s"/>
|
||||||
|
<arg name="answer" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="Info">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="info" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="Problem">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="problem" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="ChoiceListQuery">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="prompt_message" direction="in" type="s"/>
|
||||||
|
<arg name="query" direction="in" type="a{ss}"/>
|
||||||
|
<arg name="answer" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="CustomJSONRequest">
|
||||||
|
<annotation name="org.gtk.GDBus.C.Name" value="CustomJsonRequest" />
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="protocol" direction="in" type="s"/>
|
||||||
|
<arg name="version" direction="in" type="u"/>
|
||||||
|
<arg name="request" direction="in" type="s"/>
|
||||||
|
<arg name="response" direction="out" type="s"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
<interface name="org.gnome.DisplayManager.UserVerifier">
|
||||||
|
<method name="EnableExtensions">
|
||||||
|
<arg name="extensions" direction="in" type="as"/>
|
||||||
|
</method>
|
||||||
|
<method name="BeginVerification">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="BeginVerificationForUser">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="username" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="AnswerQuery">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="answer" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="Cancel">
|
||||||
|
</method>
|
||||||
|
<signal name="ConversationStarted">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="ConversationStopped">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="ReauthenticationStarted">
|
||||||
|
<arg name="pid_of_caller" type="i"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="Info">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="info" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="Problem">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="problem" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="InfoQuery">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="query" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="SecretInfoQuery">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="query" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="Reset">
|
||||||
|
</signal>
|
||||||
|
<signal name="ServiceUnavailable">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="message" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="VerificationFailed">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="VerificationComplete">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
<interface name="org.gnome.DisplayManager.UserVerifier.ChoiceList">
|
||||||
|
<method name="SelectChoice">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="choice" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<signal name="ChoiceQuery">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="prompt_message" type="s"/>
|
||||||
|
<arg name="list" type="a{ss}"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
<interface name="org.gnome.DisplayManager.UserVerifier.CustomJSON">
|
||||||
|
<method name="Reply">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="reply" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="ReportError">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="error" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<signal name="Request">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="protocol" type="s"/>
|
||||||
|
<arg name="version" type="u"/>
|
||||||
|
<arg name="request" type="s"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
<interface name="org.gnome.DisplayManager.Greeter">
|
||||||
|
<method name="SelectSession">
|
||||||
|
<arg name="session" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="SelectUser">
|
||||||
|
<arg name="username" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="BeginAutoLogin">
|
||||||
|
<arg name="username" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="GetTimedLoginDetails">
|
||||||
|
<arg name="enabled" direction="out" type="b"/>
|
||||||
|
<arg name="username" direction="out" type="s"/>
|
||||||
|
<arg name="delay" direction="out" type="i"/>
|
||||||
|
</method>
|
||||||
|
<method name="StartSessionWhenReady">
|
||||||
|
<arg name="service_name" direction="in" type="s"/>
|
||||||
|
<arg name="should_start_session" direction="in" type="b"/>
|
||||||
|
</method>
|
||||||
|
<method name="StopConflictingSession">
|
||||||
|
</method>
|
||||||
|
<signal name="SelectedUserChanged">
|
||||||
|
<arg name="username" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="DefaultLanguageNameChanged">
|
||||||
|
<arg name="language_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="DefaultSessionNameChanged">
|
||||||
|
<arg name="session_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="TimedLoginRequested">
|
||||||
|
<arg name="username" type="s"/>
|
||||||
|
<arg name="delay" type="i"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="SessionOpened">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
<arg name="session_id" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="Reauthenticated">
|
||||||
|
<arg name="service_name" type="s"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
<interface name="org.gnome.DisplayManager.RemoteGreeter">
|
||||||
|
<method name="Disconnect" />
|
||||||
|
</interface>
|
||||||
|
<interface name="org.gnome.DisplayManager.Chooser">
|
||||||
|
<method name="SelectHostname">
|
||||||
|
<arg name="hostname" direction="in" type="s"/>
|
||||||
|
</method>
|
||||||
|
<method name="Disconnect" />
|
||||||
|
</interface>
|
||||||
|
</node>
|
620
daemon/gdm-wayland-session.c
Normal file
620
daemon/gdm-wayland-session.c
Normal file
|
@ -0,0 +1,620 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* 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, 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.
|
||||||
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <locale.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
|
||||||
|
#include "gdm-common.h"
|
||||||
|
#include "gdm-settings-direct.h"
|
||||||
|
#include "gdm-settings-keys.h"
|
||||||
|
#include "gdm-log.h"
|
||||||
|
|
||||||
|
#include "gdm-manager-glue.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib-unix.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <gio/gunixinputstream.h>
|
||||||
|
|
||||||
|
#define BUS_ADDRESS_FILENO (STDERR_FILENO + 1)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GdmSettings *settings;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
|
||||||
|
GSubprocess *bus_subprocess;
|
||||||
|
GDBusConnection *bus_connection;
|
||||||
|
GdmDBusManager *display_manager_proxy;
|
||||||
|
char *bus_address;
|
||||||
|
|
||||||
|
char **environment;
|
||||||
|
|
||||||
|
GSubprocess *session_subprocess;
|
||||||
|
char *session_command;
|
||||||
|
int session_exit_status;
|
||||||
|
|
||||||
|
guint register_session_id;
|
||||||
|
|
||||||
|
GMainLoop *main_loop;
|
||||||
|
|
||||||
|
guint32 debug_enabled : 1;
|
||||||
|
} State;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_bus_finished (GSubprocess *subprocess,
|
||||||
|
GAsyncResult *result,
|
||||||
|
State *state)
|
||||||
|
{
|
||||||
|
gboolean cancelled;
|
||||||
|
|
||||||
|
cancelled = !g_subprocess_wait_finish (subprocess, result, NULL);
|
||||||
|
|
||||||
|
if (cancelled) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_subprocess_get_if_exited (subprocess)) {
|
||||||
|
int exit_status;
|
||||||
|
|
||||||
|
exit_status = g_subprocess_get_exit_status (subprocess);
|
||||||
|
|
||||||
|
g_debug ("message bus exited with status %d", exit_status);
|
||||||
|
} else {
|
||||||
|
int signal_number;
|
||||||
|
|
||||||
|
signal_number = g_subprocess_get_term_sig (subprocess);
|
||||||
|
g_debug ("message bus was killed with status %d", signal_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&state->bus_subprocess);
|
||||||
|
out:
|
||||||
|
g_main_loop_quit (state->main_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
spawn_bus (State *state,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
GDBusConnection *bus_connection = NULL;
|
||||||
|
GPtrArray *arguments = NULL;
|
||||||
|
GSubprocessLauncher *launcher = NULL;
|
||||||
|
GSubprocess *subprocess = NULL;
|
||||||
|
GInputStream *input_stream = NULL;
|
||||||
|
GDataInputStream *data_stream = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
char *bus_address_fd_string = NULL;
|
||||||
|
char *bus_address = NULL;
|
||||||
|
gsize bus_address_size;
|
||||||
|
|
||||||
|
gboolean is_running = FALSE;
|
||||||
|
int ret;
|
||||||
|
int pipe_fds[2];
|
||||||
|
|
||||||
|
g_debug ("Running session message bus");
|
||||||
|
|
||||||
|
bus_connection = g_bus_get_sync (G_BUS_TYPE_SESSION,
|
||||||
|
cancellable,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (bus_connection != NULL) {
|
||||||
|
g_debug ("session message bus already running, not starting another one");
|
||||||
|
state->bus_connection = bus_connection;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
g_debug ("could not open pipe: %s", error->message);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments = g_ptr_array_new ();
|
||||||
|
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
|
||||||
|
g_subprocess_launcher_take_fd (launcher, pipe_fds[1], BUS_ADDRESS_FILENO);
|
||||||
|
|
||||||
|
bus_address_fd_string = g_strdup_printf ("%d", BUS_ADDRESS_FILENO);
|
||||||
|
|
||||||
|
g_ptr_array_add (arguments, "dbus-daemon");
|
||||||
|
|
||||||
|
g_ptr_array_add (arguments, "--print-address");
|
||||||
|
g_ptr_array_add (arguments, bus_address_fd_string);
|
||||||
|
g_ptr_array_add (arguments, "--session");
|
||||||
|
g_ptr_array_add (arguments, NULL);
|
||||||
|
|
||||||
|
subprocess = g_subprocess_launcher_spawnv (launcher,
|
||||||
|
(const char * const *) arguments->pdata,
|
||||||
|
&error);
|
||||||
|
g_free (bus_address_fd_string);
|
||||||
|
g_clear_object (&launcher);
|
||||||
|
g_ptr_array_free (arguments, TRUE);
|
||||||
|
|
||||||
|
if (subprocess == NULL) {
|
||||||
|
g_debug ("could not start dbus-daemon: %s", error->message);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
|
||||||
|
data_stream = g_data_input_stream_new (input_stream);
|
||||||
|
g_clear_object (&input_stream);
|
||||||
|
|
||||||
|
bus_address = g_data_input_stream_read_line (data_stream,
|
||||||
|
&bus_address_size,
|
||||||
|
cancellable,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("could not read address from session message bus: %s", error->message);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bus_address == NULL) {
|
||||||
|
g_debug ("session message bus did not write address");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->bus_address = bus_address;
|
||||||
|
|
||||||
|
state->bus_subprocess = g_object_ref (subprocess);
|
||||||
|
|
||||||
|
g_subprocess_wait_async (state->bus_subprocess,
|
||||||
|
cancellable,
|
||||||
|
(GAsyncReadyCallback)
|
||||||
|
on_bus_finished,
|
||||||
|
state);
|
||||||
|
|
||||||
|
bus_connection = g_dbus_connection_new_for_address_sync (state->bus_address,
|
||||||
|
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
|
||||||
|
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
|
||||||
|
NULL,
|
||||||
|
cancellable,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (bus_connection == NULL) {
|
||||||
|
g_debug ("could not open connection to session bus: %s",
|
||||||
|
error->message);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->bus_connection = bus_connection;
|
||||||
|
is_running = TRUE;
|
||||||
|
out:
|
||||||
|
g_clear_object (&data_stream);
|
||||||
|
g_clear_object (&subprocess);
|
||||||
|
g_clear_object (&launcher);
|
||||||
|
g_clear_error (&error);
|
||||||
|
|
||||||
|
return is_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
import_environment (State *state,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
g_autoptr(GVariant) reply = NULL;
|
||||||
|
g_autoptr(GVariant) environment_variant = NULL;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
reply = g_dbus_connection_call_sync (state->bus_connection,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1",
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"Get",
|
||||||
|
g_variant_new ("(ss)",
|
||||||
|
"org.freedesktop.systemd1.Manager",
|
||||||
|
"Environment"),
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, cancellable, &error);
|
||||||
|
|
||||||
|
if (reply == NULL) {
|
||||||
|
g_debug ("could not fetch environment: %s", error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (reply, "(v)", &environment_variant);
|
||||||
|
|
||||||
|
state->environment = g_variant_dup_strv (environment_variant, NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_session_finished (GSubprocess *subprocess,
|
||||||
|
GAsyncResult *result,
|
||||||
|
State *state)
|
||||||
|
{
|
||||||
|
gboolean cancelled;
|
||||||
|
|
||||||
|
cancelled = !g_subprocess_wait_finish (subprocess, result, NULL);
|
||||||
|
|
||||||
|
if (cancelled) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_subprocess_get_if_exited (subprocess)) {
|
||||||
|
int exit_status;
|
||||||
|
|
||||||
|
exit_status = g_subprocess_get_exit_status (subprocess);
|
||||||
|
|
||||||
|
g_debug ("session exited with status %d", exit_status);
|
||||||
|
|
||||||
|
state->session_exit_status = exit_status;
|
||||||
|
} else {
|
||||||
|
int signal_number;
|
||||||
|
|
||||||
|
signal_number = g_subprocess_get_term_sig (subprocess);
|
||||||
|
g_debug ("session was killed with status %d", signal_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_object (&state->session_subprocess);
|
||||||
|
out:
|
||||||
|
g_main_loop_quit (state->main_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
spawn_session (State *state,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
GSubprocessLauncher *launcher = NULL;
|
||||||
|
GSubprocess *subprocess = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean is_running = FALSE;
|
||||||
|
int ret;
|
||||||
|
char **argv = NULL;
|
||||||
|
static const char *session_variables[] = { "DISPLAY",
|
||||||
|
"XAUTHORITY",
|
||||||
|
"WAYLAND_DISPLAY",
|
||||||
|
"WAYLAND_SOCKET",
|
||||||
|
"GNOME_SHELL_SESSION_MODE",
|
||||||
|
NULL };
|
||||||
|
/* The environment variables listed below are those we have set (or
|
||||||
|
* received from our own execution environment) only as a fallback to
|
||||||
|
* make things work, as opposed to a information directly pertaining to
|
||||||
|
* the session about to be started. Variables listed here will not
|
||||||
|
* overwrite the existing environment (possibly) imported from the
|
||||||
|
* systemd --user instance.
|
||||||
|
* As an example: We need a PATH for some of the launched subprocesses
|
||||||
|
* to work, but if the user (or the distributor) has customized the PATH
|
||||||
|
* via one of systemds user-environment-generators, that version should
|
||||||
|
* be preferred. */
|
||||||
|
static const char *fallback_variables[] = { "PATH", NULL };
|
||||||
|
|
||||||
|
g_debug ("Running wayland session");
|
||||||
|
|
||||||
|
ret = g_shell_parse_argv (state->session_command,
|
||||||
|
NULL,
|
||||||
|
&argv,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
g_debug ("could not parse session arguments: %s", error->message);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
|
||||||
|
|
||||||
|
if (state->environment != NULL) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; state->environment[i] != NULL; i++) {
|
||||||
|
g_auto(GStrv) environment_entry = NULL;
|
||||||
|
|
||||||
|
if (state->environment[i][0] == '\0') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
environment_entry = g_strsplit (state->environment[i], "=", 2);
|
||||||
|
|
||||||
|
if (environment_entry[0] == NULL || environment_entry[1] == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge the environment block imported from systemd --user with the
|
||||||
|
* environment we have set for ourselves (and thus pass on to the
|
||||||
|
* launcher process). Variables we have set have precedence, as to not
|
||||||
|
* import stale data from prior user sessions, with the exception of
|
||||||
|
* those listed in fallback_variables. See the comment there for more
|
||||||
|
* explanations. */
|
||||||
|
g_subprocess_launcher_setenv (launcher,
|
||||||
|
environment_entry[0],
|
||||||
|
environment_entry[1],
|
||||||
|
g_strv_contains (fallback_variables, environment_entry[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't allow session specific environment variables from earlier sessions to
|
||||||
|
* leak through */
|
||||||
|
for (i = 0; session_variables[i] != NULL; i++) {
|
||||||
|
if (g_getenv (session_variables[i]) == NULL) {
|
||||||
|
g_subprocess_launcher_unsetenv (launcher, session_variables[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->bus_address != NULL) {
|
||||||
|
g_subprocess_launcher_setenv (launcher, "DBUS_SESSION_BUS_ADDRESS", state->bus_address, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
subprocess = g_subprocess_launcher_spawnv (launcher,
|
||||||
|
(const char * const *) argv,
|
||||||
|
&error);
|
||||||
|
g_strfreev (argv);
|
||||||
|
|
||||||
|
if (subprocess == NULL) {
|
||||||
|
g_debug ("could not start session: %s", error->message);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->session_subprocess = g_object_ref (subprocess);
|
||||||
|
|
||||||
|
g_subprocess_wait_async (state->session_subprocess,
|
||||||
|
cancellable,
|
||||||
|
(GAsyncReadyCallback)
|
||||||
|
on_session_finished,
|
||||||
|
state);
|
||||||
|
|
||||||
|
is_running = TRUE;
|
||||||
|
out:
|
||||||
|
g_clear_object (&subprocess);
|
||||||
|
return is_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_subprocesses (State *state)
|
||||||
|
{
|
||||||
|
if (state->session_subprocess != NULL) {
|
||||||
|
g_subprocess_send_signal (state->session_subprocess, SIGTERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->bus_subprocess != NULL) {
|
||||||
|
g_subprocess_send_signal (state->bus_subprocess, SIGTERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wait_on_subprocesses (State *state)
|
||||||
|
{
|
||||||
|
if (state->bus_subprocess != NULL) {
|
||||||
|
g_subprocess_wait (state->bus_subprocess, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->session_subprocess != NULL) {
|
||||||
|
g_subprocess_wait (state->session_subprocess, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
register_display (State *state,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean registered = FALSE;
|
||||||
|
GVariantBuilder details;
|
||||||
|
|
||||||
|
g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
|
||||||
|
g_variant_builder_add (&details, "{ss}", "session-type", "wayland");
|
||||||
|
|
||||||
|
registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
|
||||||
|
g_variant_builder_end (&details),
|
||||||
|
cancellable,
|
||||||
|
&error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_debug ("Could not register display: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return registered;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_state (State **state)
|
||||||
|
{
|
||||||
|
static State state_allocation;
|
||||||
|
|
||||||
|
*state = &state_allocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_state (State **out_state)
|
||||||
|
{
|
||||||
|
State *state = *out_state;
|
||||||
|
|
||||||
|
g_clear_object (&state->cancellable);
|
||||||
|
g_clear_object (&state->bus_connection);
|
||||||
|
g_clear_object (&state->session_subprocess);
|
||||||
|
g_clear_pointer (&state->environment, g_strfreev);
|
||||||
|
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
||||||
|
g_clear_handle_id (&state->register_session_id, g_source_remove);
|
||||||
|
*out_state = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
on_sigterm (State *state)
|
||||||
|
{
|
||||||
|
g_cancellable_cancel (state->cancellable);
|
||||||
|
|
||||||
|
if (g_main_loop_is_running (state->main_loop)) {
|
||||||
|
g_main_loop_quit (state->main_loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
register_session_timeout_cb (gpointer user_data)
|
||||||
|
{
|
||||||
|
State *state;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
state = (State *) user_data;
|
||||||
|
|
||||||
|
gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
|
||||||
|
g_variant_new ("a{sv}", NULL),
|
||||||
|
state->cancellable,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("Could not register session: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
connect_to_display_manager (State *state)
|
||||||
|
{
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
state->display_manager_proxy = gdm_dbus_manager_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,
|
||||||
|
"org.gnome.DisplayManager",
|
||||||
|
"/org/gnome/DisplayManager/Manager",
|
||||||
|
state->cancellable,
|
||||||
|
&error);
|
||||||
|
|
||||||
|
if (state->display_manager_proxy == NULL) {
|
||||||
|
g_printerr ("gdm-wayland-session: could not contact display manager: %s\n",
|
||||||
|
error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
State *state = NULL;
|
||||||
|
GOptionContext *context = NULL;
|
||||||
|
static char **args = NULL;
|
||||||
|
gboolean debug = FALSE;
|
||||||
|
gboolean ret;
|
||||||
|
int exit_status = EX_OK;
|
||||||
|
static gboolean register_session = FALSE;
|
||||||
|
|
||||||
|
static GOptionEntry entries [] = {
|
||||||
|
{ "register-session", 0, 0, G_OPTION_ARG_NONE, ®ister_session, "Register session after a delay", NULL },
|
||||||
|
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||||
|
textdomain (GETTEXT_PACKAGE);
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
|
||||||
|
gdm_log_init ();
|
||||||
|
|
||||||
|
context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
|
||||||
|
g_option_context_add_main_entries (context, entries, NULL);
|
||||||
|
|
||||||
|
g_option_context_parse (context, &argc, &argv, NULL);
|
||||||
|
g_option_context_free (context);
|
||||||
|
|
||||||
|
if (args == NULL || args[0] == NULL || args[1] != NULL) {
|
||||||
|
g_warning ("gdm-wayland-session takes one argument (the session)");
|
||||||
|
exit_status = EX_USAGE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_state (&state);
|
||||||
|
|
||||||
|
state->session_command = args[0];
|
||||||
|
|
||||||
|
state->settings = gdm_settings_new ();
|
||||||
|
ret = gdm_settings_direct_init (state->settings, DATADIR "/gdm/gdm.schemas", "/");
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
g_printerr ("Unable to initialize settings\n");
|
||||||
|
exit_status = EX_DATAERR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
|
||||||
|
state->debug_enabled = debug;
|
||||||
|
|
||||||
|
gdm_log_set_debug (debug);
|
||||||
|
|
||||||
|
state->main_loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
state->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
||||||
|
|
||||||
|
ret = spawn_bus (state, state->cancellable);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
g_printerr ("Unable to run session message bus\n");
|
||||||
|
exit_status = EX_SOFTWARE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
import_environment (state, state->cancellable);
|
||||||
|
|
||||||
|
ret = spawn_session (state, state->cancellable);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
g_printerr ("Unable to run session\n");
|
||||||
|
exit_status = EX_SOFTWARE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connect_to_display_manager (state))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = register_display (state, state->cancellable);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
g_printerr ("Unable to register display with display manager\n");
|
||||||
|
exit_status = EX_SOFTWARE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (register_session) {
|
||||||
|
g_debug ("gdm-wayland-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT);
|
||||||
|
state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
|
||||||
|
register_session_timeout_cb,
|
||||||
|
state);
|
||||||
|
} else {
|
||||||
|
g_debug ("gdm-wayland-session: Session will register itself");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_main_loop_run (state->main_loop);
|
||||||
|
|
||||||
|
/* Only use exit status of session if we're here because it exit */
|
||||||
|
|
||||||
|
if (state->session_subprocess == NULL) {
|
||||||
|
exit_status = state->session_exit_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (state != NULL) {
|
||||||
|
signal_subprocesses (state);
|
||||||
|
wait_on_subprocesses (state);
|
||||||
|
clear_state (&state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_status;
|
||||||
|
}
|
1000
daemon/gdm-x-session.c
Normal file
1000
daemon/gdm-x-session.c
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue