[gdm/wip/nielsdg/meson] Allow building GDM with Meson.



commit 5e1c9907f0a827571cca344dc0254a118d3bf0b3
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Sun Jul 22 10:36:48 2018 +0200

    Allow building GDM with Meson.
    
    WIP WIP WIP WIP
    
    Solves #350.

 build-aux/autodetect-pam-config.py |  17 +++
 build-aux/find-x-server.sh         |  34 +++++
 build-aux/meson_post_install.py    |  11 ++
 chooser/meson.build                |  50 ++++++++
 common/meson.build                 |  41 ++++++
 daemon/meson.build                 | 200 +++++++++++++++++++++++++++++
 data/applications/meson.build      |  16 +++
 data/autostart/meson.build         |  12 ++
 data/dconf/meson.build             |   9 ++
 data/meson.build                   | 159 +++++++++++++++++++++++
 docs/LINGUAS                       |  22 ++++
 docs/Makefile.am                   |   2 -
 docs/meson.build                   |   6 +
 libgdm/libgdm.map                  |   6 +
 libgdm/meson.build                 |  93 ++++++++++++++
 meson.build                        | 252 +++++++++++++++++++++++++++++++++++++
 meson_options.txt                  |  40 ++++++
 pam-extensions/meson.build         |  15 +++
 pam_gdm/meson.build                |  16 +++
 po/meson.build                     |   3 +
 tests/meson.build                  |  17 +++
 utils/meson.build                  |  41 ++++++
 22 files changed, 1060 insertions(+), 2 deletions(-)
---
diff --git a/build-aux/autodetect-pam-config.py b/build-aux/autodetect-pam-config.py
new file mode 100755
index 00000000..549186ba
--- /dev/null
+++ b/build-aux/autodetect-pam-config.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python3
+
+import os;
+
+pam_configs = [('redhat', 'redhat'),
+               ('fedora', 'redhat'),
+               ('exherbo', 'exherbo'),
+               ('arch', 'arch'),
+               ('lfs', 'lfs')]
+
+for distro, pam_config in pam_configs:
+    release_file = os.path.join('/', 'etc', '{}-release'.format(distro))
+    if os.path.exists(release_file):
+        print(pam_config)
+        exit(0)
+
+print('none')
diff --git a/build-aux/find-x-server.sh b/build-aux/find-x-server.sh
new file mode 100755
index 00000000..b5a80750
--- /dev/null
+++ b/build-aux/find-x-server.sh
@@ -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
diff --git a/build-aux/meson_post_install.py b/build-aux/meson_post_install.py
new file mode 100644
index 00000000..4debe816
--- /dev/null
+++ b/build-aux/meson_post_install.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+
+install_prefix = os.environ['MESON_INSTALL_PREFIX']
+schemadir = os.path.join(install_prefix, 'share', 'glib-2.0', 'schemas')
+
+if not os.environ.get('DESTDIR'):
+  print('Compiling gsettings schemas...')
+  subprocess.call(['glib-compile-schemas', schemadir])
diff --git a/chooser/meson.build b/chooser/meson.build
new file mode 100644
index 00000000..f3b948d7
--- /dev/null
+++ b/chooser/meson.build
@@ -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'),
+)
diff --git a/common/meson.build b/common/meson.build
new file mode 100644
index 00000000..7610b620
--- /dev/null
+++ b/common/meson.build
@@ -0,0 +1,41 @@
+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 = [
+  libsystemd_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('.'),
+)
+
+# test-log exectuable
+test_log = executable('test-log',
+  'test-log.c',
+  dependencies: libgdmcommon_dep,
+  include_directories: config_h_dir,
+)
diff --git a/daemon/meson.build b/daemon/meson.build
new file mode 100644
index 00000000..7092b028
--- /dev/null
+++ b/daemon/meson.build
@@ -0,0 +1,200 @@
+# D-Bus interfaces
+display_dbus_gen = gnome.gdbus_codegen('gdm-display-glue',
+  'gdm-display.xml',
+  namespace: 'GdmDBus',
+  interface_prefix: 'org.gnome.DisplayManager',
+  autocleanup: 'all',
+)
+local_display_dbus_gen = gnome.gdbus_codegen('gdm-local-display-glue',
+  'gdm-local-display.xml',
+  namespace: 'GdmDBus',
+  interface_prefix: 'org.gnome.DisplayManager',
+  autocleanup: 'all',
+)
+local_display_factory_dbus_gen = gnome.gdbus_codegen('gdm-local-display-factory-glue',
+  'gdm-local-display-factory.xml',
+  namespace: 'GdmDBus',
+  interface_prefix: 'org.gnome.DisplayManager',
+  autocleanup: 'all',
+)
+manager_dbus_gen = gnome.gdbus_codegen('gdm-manager-glue',
+  'gdm-manager.xml',
+  namespace: 'GdmDBus',
+  interface_prefix: 'org.gnome.DisplayManager',
+  autocleanup: 'all',
+)
+session_dbus_gen = gnome.gdbus_codegen('gdm-session-glue',
+  'gdm-session.xml',
+  namespace: 'GdmDBus',
+  interface_prefix: 'org.gnome.DisplayManager',
+  autocleanup: 'all',
+)
+session_worker_dbus_gen = gnome.gdbus_codegen('gdm-session-worker-glue',
+  'gdm-session-worker.xml',
+  namespace: 'GdmDBus',
+  interface_prefix: 'org.gnome.DisplayManager',
+  autocleanup: 'all',
+)
+
+gdm_session_enums = gnome.mkenums('gdm-session-enum-types',
+  h_template: 'gdm-session-enum-types.h.in',
+  c_template: 'gdm-session-enum-types.c.in',
+  sources: 'gdm-session.h',
+)
+gdm_session_worker_enums = gnome.mkenums('gdm-session-worker-enum-types',
+  h_template: 'gdm-session-worker-enum-types.h.in',
+  c_template: 'gdm-session-worker-enum-types.c.in',
+  sources: 'gdm-session-worker.h',
+)
+
+# Daemons deps
+gdm_daemon_deps = [
+  libgdmcommon_dep,
+  accountsservice_dep,
+  gobject_dep,
+  gio_dep,
+  gio_unix_dep,
+  libpam_dep,
+  x_deps,
+  xcb_dep,
+]
+
+if xdmcp_dep.found() and get_option('tcp-wrappers')
+  gdm_daemon_deps += libwrap_dep
+endif
+
+# test-session-client
+test_session_client_src = [
+  'test-session-client.c',
+  session_dbus_gen,
+  manager_dbus_gen,
+]
+
+test_session_client = executable('test-session-client',
+  test_session_client_src,
+  dependencies: gdm_daemon_deps,
+  include_directories: config_h_dir,
+)
+
+# Session worker
+gdm_session_worker_src = [
+  'session-worker-main.c',
+  'gdm-session.c',
+  'gdm-session-settings.c',
+  'gdm-session-auditor.c',
+  'gdm-session-record.c',
+  'gdm-session-worker.c',
+  'gdm-session-worker-job.c',
+  'gdm-session-worker-common.c',
+  'gdm-dbus-util.c',
+  session_dbus_gen,
+  session_worker_dbus_gen,
+  gdm_session_enums,
+  gdm_session_worker_enums,
+]
+
+gdm_session_worker_deps = [
+  gdm_daemon_deps,
+]
+
+gdm_session_worker_includes = [
+  config_h_dir,
+]
+
+if pam_extensions_supported
+  gdm_session_worker_src += '../pam-extensions/gdm-pam-extensions.h'
+  gdm_session_worker_includes += pam_extensions_includedir
+endif
+
+if libaudit_dep.found()
+  gdm_session_worker_deps += libaudit_dep
+
+  gdm_session_worker_src += [
+    'gdm-session-linux-auditor.c',
+  ]
+endif
+
+if have_adt
+  gdm_session_worker_src += 'gdm-session-solaris-auditor.c'
+endif
+
+gdm_session_worker = executable('gdm-session-worker',
+  gdm_session_worker_src,
+  dependencies: gdm_daemon_deps,
+  include_directories: gdm_session_worker_includes,
+  install: true,
+  install_dir: get_option('libexecdir'),
+)
+
+# Wayland session
+gdm_wayland_session_src = [
+  'gdm-wayland-session.c',
+  manager_dbus_gen,
+]
+
+gdm_wayland_session = executable('gdm-wayland-session',
+  gdm_wayland_session_src,
+  dependencies: gdm_daemon_deps,
+  include_directories: gdm_session_worker_includes,
+  install: true,
+  install_dir: get_option('libexecdir'),
+)
+
+# X session
+gdm_x_session_src = [
+  'gdm-x-session.c',
+  manager_dbus_gen,
+]
+
+gdm_x_session = executable('gdm-x-session',
+  gdm_x_session_src,
+  dependencies: gdm_daemon_deps,
+  include_directories: gdm_session_worker_includes,
+  install: true,
+  install_dir: get_option('libexecdir'),
+)
+
+# GDM daemon
+gdm_daemon_src = [
+  'gdm-dbus-util.c',
+  'gdm-display-access-file.c',
+  'gdm-display-factory.c',
+  'gdm-display-store.c',
+  'gdm-display.c',
+  'gdm-launch-environment.c',
+  'gdm-legacy-display.c',
+  'gdm-local-display-factory.c',
+  'gdm-local-display.c',
+  'gdm-manager.c',
+  'gdm-server.c',
+  'gdm-session-record.c',
+  'gdm-session-worker-common.c',
+  'gdm-session-worker-job.c',
+  'gdm-session.c',
+  'main.c',
+  display_dbus_gen,
+  local_display_factory_dbus_gen,
+  manager_dbus_gen,
+  local_display_dbus_gen,
+  session_dbus_gen,
+  session_worker_dbus_gen,
+  gdm_session_enums,
+]
+
+if xdmcp_dep.found()
+  gdm_daemon_deps += xdmcp_dep
+
+  gdm_daemon_src += [
+    'gdm-xdmcp-display-factory.c',
+    'gdm-xdmcp-display.c',
+    'gdm-xdmcp-chooser-display.c',
+  ]
+endif
+
+gdm_daemon = executable('gdm',
+  gdm_daemon_src,
+  dependencies: gdm_daemon_deps,
+  include_directories: config_h_dir,
+  install: true,
+  install_dir: get_option('sbindir')
+)
diff --git a/data/applications/meson.build b/data/applications/meson.build
new file mode 100644
index 00000000..48a2f099
--- /dev/null
+++ b/data/applications/meson.build
@@ -0,0 +1,16 @@
+desktop_conf = {
+  'LIBDIR': gdm_prefix / get_option('libdir'),
+  'LIBEXECDIR': gdm_prefix / get_option('libexecdir'),
+  'LOCALSTATEDIR': gdm_prefix / get_option('localstatedir'),
+  'SBINDIR': gdm_prefix / get_option('sbindir'),
+  'SYSCONFDIR': gdm_prefix / get_option('sysconfdir'),
+}
+
+foreach desktop_file : [ 'mime-dummy-handler.desktop', 'mimeapps.list' ]
+  configure_file(
+    input: desktop_file,
+    output: desktop_file,
+    configuration: desktop_conf,
+    install_dir: get_option('datadir') / 'gdm' / 'greeter' / 'applications',
+  )
+endforeach
diff --git a/data/autostart/meson.build b/data/autostart/meson.build
new file mode 100644
index 00000000..348a6c69
--- /dev/null
+++ b/data/autostart/meson.build
@@ -0,0 +1,12 @@
+autostart_files_conf = {
+  'LIBEXECDIR': gdm_prefix / get_option('libexecdir'),
+}
+
+foreach autostart_file : [ 'orca-autostart.desktop' ]
+  configure_file(
+    input: autostart_file,
+    output: autostart_file,
+    configuration: autostart_files_conf,
+    install_dir: get_option('datadir') / 'gdm' / 'greeter' / 'autostart',
+  )
+endforeach
diff --git a/data/dconf/meson.build b/data/dconf/meson.build
new file mode 100644
index 00000000..0ddad712
--- /dev/null
+++ b/data/dconf/meson.build
@@ -0,0 +1,9 @@
+gdm_dconf = configure_file(
+  input: 'gdm.in',
+  output: 'gdm',
+  configuration: {
+    'DATADIR': gdm_prefix / get_option('datadir'),
+    'PACKAGE': meson.project_name(),
+  },
+  install_dir: get_option('datadir') / 'dconf' / 'profile',
+)
diff --git a/data/meson.build b/data/meson.build
new file mode 100644
index 00000000..8522e4dc
--- /dev/null
+++ b/data/meson.build
@@ -0,0 +1,159 @@
+subdir('applications')
+subdir('autostart')
+subdir('dconf')
+
+# XPath configs
+foreach file : [ 'Init', 'PreSession', 'PostSession' ]
+  configure_file(
+    input: '@0@.in'.format(file),
+    output: file,
+    configuration: { 'X_PATH':  x_path },
+  )
+endforeach
+
+# gdm.conf
+configure_file(
+  output: 'gdm.conf',
+  input: 'gdm.conf.in',
+  configuration: { 'GDM_USERNAME': get_option('user') },
+  install_dir: dbus_sys_dir,
+)
+configure_file(
+  output: 'gdm.conf-custom',
+  input: 'gdm.conf-custom.in',
+  copy: true,
+  install_mode: 'rw-r--r--',
+  install_dir: gdmconfdir,
+)
+
+# GSettings schema
+install_data('org.gnome.login-screen.gschema.xml',
+  install_dir: get_option('datadir') / 'glib-2.0' / 'schemas',
+)
+compiled_gschema = gnome.compile_schemas()
+
+# gdm.schema
+gdm_schema_conf = {
+  'GDM_USERNAME': get_option('user'),
+  'GDM_GROUPNAME': get_option('group'),
+  'gdmconfdir': gdmconfdir,
+}
+gdm_schema = configure_file(
+  input: 'gdm.schemas.in',
+  output: 'gdm.schemas',
+  configuration: gdm_schema_conf,
+  install_dir: get_option('datadir') / 'gdm',
+)
+
+install_data('locale.alias',
+  install_dir: get_option('datadir') / 'gdm',
+)
+configure_file(
+  input: 'gnome-login.session.in',
+  output: 'gnome-login.session',
+  configuration: {
+    'libexecdir': gdm_prefix / get_option('libexecdir'),
+    'check_accelerated_dir': check_accelerated_dir,
+  },
+  install_dir: get_option('datadir') / 'gnome-session' / 'sessions',
+)
+
+# PAM
+pam_data_files_map = {
+  'redhat': [
+    'gdm-autologin',
+    'gdm-launch-environment',
+    'gdm-fingerprint',
+    'gdm-smartcard',
+    'gdm-password',
+    'gdm-pin',
+  ],
+  'openembedded': [
+    'gdm-autologin',
+    'gdm-launch-environment',
+    'gdm-password',
+    'gdm-pin',
+  ],
+  'exherbo': [
+    'gdm-autologin',
+    'gdm-launch-environment',
+    'gdm-fingerprint',
+    'gdm-smartcard',
+    'gdm-password',
+    'gdm-pin',
+  ],
+  'lfs': [
+    'gdm-autologin',
+    'gdm-launch-environment',
+    'gdm-fingerprint',
+    'gdm-smartcard',
+    'gdm-password',
+    'gdm-pin',
+  ],
+  'arch': [
+    'gdm-autologin',
+    'gdm-launch-environment',
+    'gdm-fingerprint',
+    'gdm-smartcard',
+    'gdm-password',
+    'gdm-pin',
+  ],
+  'none': [],
+  # We should no longer have 'autodetect' at this point
+}
+
+pam_data_files = pam_data_files_map[default_pam_config]
+pam_prefix = (get_option('pam-prefix') != '')? get_option('pam-prefix') : get_option('sysconfdir')
+foreach _pam_filename : pam_data_files
+  install_data('pam-@0@/@1@.pam'.format(default_pam_config, _pam_filename),
+    rename: _pam_filename,
+    install_dir: pam_prefix / 'pam.d',
+  )
+endforeach
+
+gdm_rules = configure_file(
+  input: '61-gdm.rules.in',
+  output: '61-gdm.rules',
+  configuration: {
+    'libexecdir': gdm_prefix / get_option('libexecdir'),
+  },
+  install_dir: udev_dir,
+)
+
+# DBus service files
+service_config = configuration_data()
+service_config.set('sbindir', gdm_prefix / get_option('sbindir'))
+service_config.set('GDM_INITIAL_VT', get_option('initial-vt'))
+service_config.set('LANG_CONFIG_FILE', lang_config_file)
+if plymouth_dep.found()
+  service_config.set('PLYMOUTH_QUIT_SERVICE', 'plymouth-quit.service')
+else
+  service_config.set('PLYMOUTH_QUIT_SERVICE', '')
+endif
+
+if get_option('systemdsystemunitdir') != ''
+  systemd_systemunitdir = get_option('systemdsystemunitdir')
+else
+  systemd_systemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir')
+endif
+
+configure_file(
+  input: 'gdm.service.in',
+  output: 'gdm.service',
+  configuration: service_config,
+  install_dir: systemd_systemunitdir,
+)
+
+# XSession
+if get_option('gdm-xsession')
+  xsession_shell = get_option('solaris')? '/bin/ksh' : '/bin/sh'
+  configure_file(
+    input: 'XSession.in',
+    output: 'XSession',
+    configuration: {
+      'libexecdir': gdm_prefix / get_option('libexecdir'),
+      'XSESSION_SHELL': xsession_shell,
+    },
+    install_dir: gdmconfdir,
+  )
+endif
diff --git a/docs/LINGUAS b/docs/LINGUAS
new file mode 100644
index 00000000..c7897364
--- /dev/null
+++ b/docs/LINGUAS
@@ -0,0 +1,22 @@
+ca
+cs
+de
+el
+en_GB
+es
+fr
+gl
+hu
+id
+it
+ko
+oc
+pt_BR
+ro
+ru
+sl
+sv
+te
+tr
+uk
+zh_CN
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 7e7fac64..ed20a002 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -5,5 +5,3 @@ HELP_ID = gdm
 HELP_FILES = \
        index.docbook   \
        legal.xml
-
-HELP_LINGUAS = ca cs de el en_GB es fr gl hu id it ko oc pt_BR ro ru sl sv te tr uk zh_CN
diff --git a/docs/meson.build b/docs/meson.build
new file mode 100644
index 00000000..52bac4ca
--- /dev/null
+++ b/docs/meson.build
@@ -0,0 +1,6 @@
+gnome.yelp(meson.project_name(),
+  sources: [
+    'index.docbook',
+    'legal.xml',
+  ],
+)
diff --git a/libgdm/libgdm.map b/libgdm/libgdm.map
new file mode 100644
index 00000000..6a1c7fa1
--- /dev/null
+++ b/libgdm/libgdm.map
@@ -0,0 +1,6 @@
+{
+global:
+  *;
+local:
+  _*;
+};
diff --git a/libgdm/meson.build b/libgdm/meson.build
new file mode 100644
index 00000000..a0e04242
--- /dev/null
+++ b/libgdm/meson.build
@@ -0,0 +1,93 @@
+libgdm_manager_dbus_gen = gnome.gdbus_codegen('gdm-manager-glue',
+    sources: '..' / 'daemon' / 'gdm-manager.xml',
+    namespace: 'Gdm',
+    interface_prefix: 'org.gnome.DisplayManager',
+    autocleanup: 'all',
+    annotations: [
+      [ 'org.gnome.DisplayManager.Manager', 'org.gtk.GDBus.C.Name', 'Manager' ],
+    ],
+    build_by_default: true,
+)
+libgdm_client_dbus_gen = gnome.gdbus_codegen('gdm-client-glue',
+    sources: '..' / 'daemon' / 'gdm-session.xml',
+    namespace: 'Gdm',
+    interface_prefix: 'org.gnome.DisplayManager',
+    autocleanup: 'all',
+    annotations: [
+      [ 'org.gnome.DisplayManager.UserVerifier', 'org.gtk.GDBus.C.Name', 'UserVerifier' ],
+      [ 'org.gnome.DisplayManager.Greeter', 'org.gtk.GDBus.C.Name', 'Greeter' ],
+      [ 'org.gnome.DisplayManager.RemoteGreeter', 'org.gtk.GDBus.C.Name', 'RemoteGreeter' ],
+      [ 'org.gnome.DisplayManager.Chooser', 'org.gtk.GDBus.C.Name', 'Chooser' ],
+    ],
+    build_by_default: true,
+)
+
+libgdm_built_sources = [
+  libgdm_manager_dbus_gen,
+  libgdm_client_dbus_gen,
+]
+
+libgdm_sources = files(
+  'gdm-client.c',
+  'gdm-sessions.c',
+  'gdm-user-switching.c',
+)
+
+libgdm_headers = [
+  'gdm-client.h',
+  'gdm-sessions.h',
+  'gdm-user-switching.h',
+  libgdm_client_dbus_gen[1],
+  libgdm_manager_dbus_gen[1],
+]
+
+libgdm_deps = [
+  glib_dep,
+  gio_dep,
+  gio_unix_dep,
+  libsystemd_dep,
+  libgdmcommon_dep,
+]
+
+libgdm_link_flags = [
+  '-Wl,--version-script,@0@/libgdm.map'.format(meson.current_source_dir()),
+]
+
+libgdm = library('gdm',
+  libgdm_sources + libgdm_built_sources,
+  version: '1.0.0',
+  dependencies: libgdm_deps,
+  include_directories: config_h_dir,
+  link_args: libgdm_link_flags,
+  install: true,
+)
+
+libgdm_gir_includes = [
+  'GLib-2.0',
+  'GObject-2.0',
+  'Gio-2.0',
+]
+
+libgdm_dep = declare_dependency(
+  link_with: libgdm,
+  dependencies: libgdm_deps,
+  include_directories: include_directories('.'),
+  sources: libgdm_built_sources,
+)
+
+libgdm_gir = gnome.generate_gir(libgdm,
+  sources: libgdm_headers,
+  namespace: 'Gdm',
+  nsversion: '1.0',
+  identifier_prefix: 'Gdm',
+  includes: libgdm_gir_includes,
+  install: true,
+)
+
+# Pkg-config file
+pkgconfig.generate(libgdm,
+  name: 'GDM Client Library',
+  description: 'Client Library for communicating with GDM daemon',
+  filebase: meson.project_name(),
+  requires: gobject_dep,
+)
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000..2bb76d56
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,252 @@
+project('gdm', 'c',
+  version: '3.33.90',
+  license: 'GPL2+',
+  meson_version: '>= 0.49',
+)
+
+# Modules
+gnome = import('gnome')
+pkgconfig = import('pkgconfig')
+i18n = import('i18n')
+
+# Compiler
+cc = meson.get_compiler('c')
+
+# Options
+gdm_prefix = get_option('prefix')
+
+gdmconfdir = (get_option('sysconfsubdir') == '')? gdm_prefix / get_option('sysconfdir') : gdm_prefix / 
get_option('sysconfdir') / get_option('sysconfsubdir')
+dmconfdir = (get_option('dmconfdir') != '')? get_option('dmconfdir') : gdm_prefix / get_option('sysconfdir') 
/ 'dm'
+udev_dir = get_option('udev-dir') != '' ? get_option('udev-dir') : get_option('libdir') / 'udev' / 'rules.d'
+at_spi_registryd_dir = (get_option('at-spi-registryd-dir') != '')? get_option('at-spi-registryd-dir') : 
gdm_prefix / get_option('libexecdir')
+lang_config_file = (get_option('lang-file') != '')? get_option('lang-file') : gdm_prefix / 
get_option('sysconfdir') / 'locale.conf'
+pam_mod_dir = (get_option('pam-mod-dir') != '')? get_option('pam-mod-dir') : gdm_prefix / 
get_option('libdir') / 'security'
+dbus_sys_dir = (get_option('dbus-sys') != '')? get_option('dbus-sys') : get_option('sysconfdir') / 'dbus-1' 
/ 'system.d'
+dbus_services = get_option('dbus-services')
+gdm_defaults_conf = (get_option('defaults-conf') != '')? get_option('defaults-conf') : gdm_prefix / 
get_option('datadir') / 'gdm' / 'defaults.conf'
+gdm_custom_conf = (get_option('custom-conf') != '')? get_option('custom-conf') : gdmconfdir / 'custom.conf'
+gdm_runtime_conf = (get_option('runtime-conf') != '')? get_option('runtime-conf') : gdm_custom_conf
+gnome_settings_daemon_dir = (get_option('gnome-settings-daemon-dir') != '')? 
get_option('gnome-settings-daemon-dir') : gdm_prefix / get_option('libexecdir')
+check_accelerated_dir = (get_option('check-accelerated-dir') != '')? get_option('check-accelerated-dir') : 
gdm_prefix / get_option('libexecdir')
+gdm_run_dir = (get_option('run-dir') != '')? get_option('run-dir') : gdm_prefix / 
get_option('localstatedir') / 'run' / 'gdm'
+gdm_pid_file = (get_option('pid-file') != '')? get_option('pid-file') : gdm_run_dir / 'gdm.pid'
+ran_once_marker_dir = (get_option('ran-once-marker-dir') != '')? get_option('ran-once-marker-dir') : 
gdm_run_dir
+working_dir = (get_option('working-dir') != '')? get_option('working-dir') : gdm_prefix / 
get_option('localstatedir') / 'lib' / 'gdm'
+gdm_xauth_dir = (get_option('xauth-dir') != '')? get_option('xauth-dir') : gdm_run_dir
+gdm_screenshot_dir = (get_option('screenshot-dir') != '')? get_option('screenshot-dir') : gdm_run_dir / 
'greeter'
+
+# Common variables
+config_h_dir = include_directories('.')
+
+# Dependencies
+glib_min_version = '2.44.0'
+
+glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
+gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
+gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version)
+gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
+gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1')
+libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4')
+accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35')
+xcb_dep = dependency('xcb')
+keyutils_dep = cc.find_library('keyutils', required: false)
+libselinux_dep = dependency('libselinux', required: get_option('selinux'))
+# X11
+x_deps = declare_dependency(
+  dependencies: [
+    dependency('x11'),
+    dependency('xau'),
+  ],
+)
+find_x_server_script = find_program('build-aux/find-x-server.sh', native: true)
+find_x_server_out = run_command(find_x_server_script).stdout().strip()
+if find_x_server_out != ''
+  x_bin = find_x_server_out
+  x_bin_path_split = x_bin.split('/')
+  i = 0
+  x_path = '/'
+  foreach dir : x_bin_path_split
+    if i < x_bin_path_split.length() - 1
+      x_path = x_path / dir
+    endif
+    i = i + 1
+  endforeach
+else
+  # what to do, what to do, this is wrong, but this just sets the
+  # defaults, perhaps this user is cross compiling or some such
+  x_path = '/usr/bin/X11:/usr/X11R6/bin:/opt/X11R6/bin'
+  x_bin = '/usr/bin/X'
+endif
+xdmcp_dep = cc.find_library('Xdmcp', required: get_option('xdmcp'))
+if xdmcp_dep.found() and get_option('tcp-wrappers')
+  libwrap_dep = cc.find_library('libwrap')
+endif
+# systemd
+systemd_dep = dependency('systemd')
+libsystemd_dep = dependency('libsystemd')
+journald_dep = dependency('journald', required: get_option('systemd-journal'))
+systemd_multiseat_x = find_program('systemd-multi-seat-x', required: false)
+systemd_x_server = systemd_multiseat_x.found()? systemd_multiseat_x.path() : 
'/lib/systemd/systemd-multi-seat-x'
+# Plymouth
+plymouth_dep = dependency('ply-boot-client', required: get_option('plymouth'))
+# Check for Solaris auditing API (ADT)
+# Note, Solaris auditing not supported for Solaris 9 or earlier and
+# should not be used on these versions of Solaris if auditing is
+# required.  Solaris auditing is only supported on systems that
+# support the ADT_USER enumeration value.
+have_adt = cc.has_header_symbol('bsm/adt.h', 'ADT_USER')
+# libaudit
+libaudit_dep = dependency('libaudit_dep', required: get_option('libaudit'))
+# unit testsheadername
+libcheck_dep = dependency('check', version: '>= 0.9.4')
+
+cc.has_header('security/pam_modutil.h')
+cc.has_header('security/pam_ext.h')
+have_pam_syslog = cc.has_function('pam_syslog', args: 'pam')
+
+# UTMP
+have_utmpx_header = cc.has_header('utmpx.h')
+have_utmp_header =  cc.has_header('utmp.h')
+utmp_struct = have_utmpx_header? 'struct utmpx' : 'struct utmp'
+utmp_include =  have_utmpx_header? '#include <utmpx.h>' : '#include <utmp.h>'
+utmp_has_host_field = cc.has_member(utmp_struct, 'ut_host', prefix: utmp_include)
+utmp_has_pid_field = cc.has_member(utmp_struct, 'ut_pid', prefix: utmp_include)
+utmp_has_id_field = cc.has_member(utmp_struct, 'ut_id', prefix: utmp_include)
+utmp_has_name_field = cc.has_member(utmp_struct, 'ut_name', prefix: utmp_include)
+utmp_has_type_field = cc.has_member(utmp_struct, 'ut_type', prefix: utmp_include)
+utmp_has_exit_e_termination_field = cc.has_member(utmp_struct, 'ut_exit.e_termination', prefix: utmp_include)
+utmp_has_user_field = cc.has_member(utmp_struct, 'ut_user', prefix: utmp_include)
+utmp_has_time_field = cc.has_member(utmp_struct, 'ut_time', prefix: utmp_include)
+utmp_has_tv_field = cc.has_member(utmp_struct, 'ut_tv', prefix: utmp_include)
+utmp_has_syslen_field = cc.has_member(utmp_struct, 'ut_syslen', prefix: utmp_include)
+
+# Check for POSIX getpwnam_r
+have_posix_getpwnam_r = cc.compiles('''
+#define _POSIX_PTHREAD_SEMANTICS
+#include <errno.h>
+#include <pwd.h>
+
+int main(int argc, char **argv) {
+  char buffer[10000];
+  struct passwd pwd, *pwptr = &pwd;
+  int error;
+  errno = 0;
+  error = getpwnam_r ("", &pwd, buffer,
+                      sizeof (buffer), &pwptr);
+   return (error < 0 && errno == ENOSYS)
+     || error == ENOSYS;
+}
+''')
+
+# PAM
+libpam_dep = cc.find_library('pam')
+pam_extensions_supported = cc.has_header_symbol('security/pam_appl.h', 'PAM_BINARY_PROMPT')
+
+default_pam_config = get_option('default-pam-config')
+# If requested, try autodetecting from release files (see NetworkManager source) 
+if default_pam_config == 'autodetect'
+  pam_autodetect_map = {
+    '/etc/redhat-release': 'redhat',
+    '/etc/fedora-release': 'redhat',
+    '/etc/exherbo-release': 'exherbo',
+    '/etc/arch-release': 'arch',
+    '/etc/lfs-release': 'lfs',
+  }
+
+  foreach _file, _pam_conf : pam_autodetect_map
+    pam_file_check = run_command('test', '-f', _file)
+    if pam_file_check.returncode() == 0
+      default_pam_config = _pam_conf
+    endif
+  endforeach
+
+  # If still not detected, default to none
+  if default_pam_config == 'autodetect'
+    default_pam_config = 'none'
+  endif
+endif
+
+# Configuration
+conf = configuration_data()
+conf.set_quoted('G_LOG_DOMAIN', 'Gdm')
+conf.set_quoted('VERSION', meson.project_version())
+conf.set_quoted('PACKAGE_VERSION', meson.project_version())
+conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
+conf.set_quoted('DATADIR', gdm_prefix / get_option('datadir'))
+conf.set_quoted('BINDIR', gdm_prefix / get_option('bindir'))
+conf.set_quoted('LIBDIR', gdm_prefix / get_option('libdir'))
+conf.set_quoted('LIBEXECDIR', gdm_prefix / get_option('libexecdir'))
+conf.set_quoted('LOGDIR', get_option('log-dir'))
+conf.set_quoted('DMCONFDIR', dmconfdir)
+conf.set_quoted('GDMCONFDIR', gdmconfdir)
+conf.set_quoted('GDM_SCREENSHOT_DIR', gdm_screenshot_dir)
+conf.set_quoted('GDM_CACHE_DIR', gdm_prefix / get_option('localstatedir') / 'cache' / 'gdm')
+conf.set_quoted('GDM_XAUTH_DIR', gdm_xauth_dir)
+conf.set_quoted('GDM_RAN_ONCE_MARKER_DIR', ran_once_marker_dir)
+conf.set_quoted('GDM_RUN_DIR', gdm_run_dir)
+conf.set_quoted('GNOMELOCALEDIR', gdm_prefix / get_option('datadir') / get_option('localedir'))
+conf.set_quoted('AT_SPI_REGISTRYD_DIR', at_spi_registryd_dir)
+conf.set_quoted('GDM_PID_FILE', gdm_pid_file)
+conf.set_quoted('GNOME_SETTINGS_DAEMON_DIR', gnome_settings_daemon_dir)
+conf.set_quoted('CHECK_ACCELRATED_DIR', check_accelerated_dir)
+conf.set_quoted('LANG_CONFIG_FILE', lang_config_file)
+conf.set('HAVE_ADT', have_adt)
+conf.set('HAVE_UTMP_H', have_utmp_header)
+conf.set('HAVE_UTMPX_H', have_utmpx_header)
+conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r)
+conf.set('UTMP', utmp_struct)
+conf.set('HAVE_GETUTXENT', cc.has_function('getutxent'))
+conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp'))
+conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx'))
+conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil'))
+conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil'))
+conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil'))
+conf.set('HAVE_PAM_SYSLOG', have_pam_syslog)
+conf.set('HAVE_KEYUTILS', keyutils_dep.found())
+conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported)
+conf.set('HAVE_SELINUX', libselinux_dep.found())
+conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server'))
+conf.set('ENABLE_SYSTEMD_JOURNAL', journald_dep.found())
+conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support'))
+conf.set('ENABLE_PROFILING', get_option('profiling'))
+conf.set('GDM_INITIAL_VT', get_option('initial-vt'))
+conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf)
+conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf)
+conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf)
+conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path'))
+conf.set_quoted('GDM_USERNAME', get_option('user'))
+conf.set_quoted('GDM_GROUPNAME', get_option('group'))
+conf.set('HAVE_LIBXDMCP', xdmcp_dep.found())
+conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server)
+conf.set('WITH_PLYMOUTH', plymouth_dep.found())
+conf.set_quoted('X_SERVER', x_bin)
+conf.set_quoted('X_PATH', x_path)
+conf.set('HAVE_UT_UT_HOST', utmp_has_host_field)
+conf.set('HAVE_UT_UT_PID', utmp_has_pid_field)
+conf.set('HAVE_UT_UT_ID', utmp_has_id_field)
+conf.set('HAVE_UT_UT_NAME', utmp_has_name_field)
+conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field)
+conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field)
+conf.set('HAVE_UT_UT_USER', utmp_has_user_field)
+conf.set('HAVE_UT_UT_TIME', utmp_has_time_field)
+conf.set('HAVE_UT_UT_TV', utmp_has_tv_field)
+conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field)
+conf.set('ENABLE_IPV6', get_option('ipv6'))
+configure_file(output: 'config.h', configuration: conf)
+
+# Subdirs
+subdir('data')
+subdir('common')
+if pam_extensions_supported
+  subdir('pam-extensions')
+endif
+subdir('daemon')
+subdir('libgdm')
+subdir('utils')
+subdir('pam_gdm')
+subdir('po')
+subdir('tests')
+if xdmcp_dep.found()
+  subdir('chooser')
+endif
+subdir('docs')
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000..16db86fa
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,40 @@
+option('at-spi-registryd-dir', type: 'string', value: '', description: 'Specify the directory of 
at-spi-registryd.')
+option('check-accelerated-dir', type: 'string', value: '', description: 'Specify the directory of 
gnome-session-check-accelerated.')
+option('custom-conf', type: 'string', value: '', description: 'Filename to give to custom configuration 
file.')
+option('dbus-services', type: 'string', value: '', description: 'Where D-Bus services directory is.')
+option('dbus-sys', type: 'string', value: '', description: 'Where D-Bus systemd directory is.')
+option('default-pam-config', type: 'combo', choices: [ 'autodetect', 'redhat', 'openembedded', 'exherbo', 
'lfs', 'arch', 'none'], value: 'autodetect', description: '')
+option('default-path', type: 'string', value: 
'/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin', description: 'Path GDM will use as the 
user\'s default PATH.')
+option('defaults-conf', type: 'string', value: '', description: 'Filename to give to defaults file.')
+option('dmconfdir', type: 'string', value: '', description: 'Directory where sessions are stored.')
+option('gdm-xsession', type: 'boolean', value: false, description: 'Enable installing the gdm Xsession 
file.')
+option('gnome-settings-daemon-dir', type: 'string', value: '', description: 'Specify the directory of 
gnome-settings-daemon used by the chooser.')
+option('group', type: 'string', value: 'gdm', description: 'GDM\'s group.')
+option('initial-vt', type: 'integer', value: 1, description: 'Initial virtual terminal to use.')
+option('ipv6', type: 'boolean', value: false, description: 'Enables compilation of IPv6 code.')
+option('lang-file', type: 'string', value: '', description: 'File containing default language settings.')
+option('libaudit', type: 'feature', value: 'auto', description: 'Add Linux audit support.')
+option('log-dir', type: 'string', value: '/var/log/gdm', description: 'Log directory.')
+option('pam-mod-dir', type: 'string', value: '', description: 'Directory to install PAM modules in.')
+option('pam-prefix', type: 'string', value: '', description: 'Specify where PAM files go.')
+option('pid-file', type: 'string', value: '', description: 'Pid file.')
+option('plymouth', type: 'feature', value: 'auto', description: 'Add plymouth support.')
+option('profiling', type: 'boolean', value: false, description: 'Enable profiling.')
+option('ran-once-marker-dir', type: 'string', value: '', description: 'Ran once marker directory.')
+option('run-dir', type: 'string', value: '', description: 'Runtime directory.')
+option('runtime-conf', type: 'string', value: '', description: 'Filename to give to runtime configuration 
file.')
+option('screenshot-dir', type: 'string', value: '', description: 'Directory to store greeter screenshot.')
+option('selinux', type: 'feature', value: 'auto', description: 'Add SELinux support.')
+option('solaris', type: 'boolean', value: false, description: 'Build for Solaris')
+option('split-authentication', type: 'boolean', value: true, description: 'Enable multiple simultaneous PAM 
conversations during login.')
+option('sysconfsubdir', type: 'string', value: 'gdm', description: 'Directory name used under sysconfdir.')
+option('systemd-journal', type: 'boolean', value: false, description: 'Add journald support.')
+option('systemdsystemunitdir', type: 'string', value: '', description: 'Directory for systemd service 
files.')
+option('tcp-wrappers', type: 'boolean', value: false, description: 'Use TCP wrappers.')
+option('udev-dir', type: 'string', value: '', description: 'Directory for udev rules file.')
+option('user', type: 'string', value: 'gdm', description: 'GDM\'s username.')
+option('user-display-server', type: 'boolean', value: true, description: 'Enable running X server as user.')
+option('wayland-support', type: 'boolean', value: true, description: 'Enable support for wayland sessions.')
+option('working-dir', type: 'string', value: '', description: 'Working directory.')
+option('xauth-dir', type: 'string', value: '', description: 'XAuth cookie directory.')
+option('xdmcp', type: 'feature', value: 'auto', description: 'Add XDMCP (remote login) support.')
diff --git a/pam-extensions/meson.build b/pam-extensions/meson.build
new file mode 100644
index 00000000..a4a9dc40
--- /dev/null
+++ b/pam-extensions/meson.build
@@ -0,0 +1,15 @@
+if pam_extensions_supported
+  pkgconfig.generate(
+    name: 'GDM PAM Extensions',
+    description: 'Macros for custom protocols over PAM',
+    filebase: 'gdm-pam-extensions',
+    version: meson.project_version(),
+    subdirs: 'gdm',
+    variables: [
+      # NOTE: Meson does not provide an exec_prefix option, is it necessary for GDM though?
+      'exec_prefix=' + get_option('prefix'),
+    ],
+  )
+
+  pam_extensions_includedir = include_directories('.')
+endif
diff --git a/pam_gdm/meson.build b/pam_gdm/meson.build
new file mode 100644
index 00000000..f47d8e6a
--- /dev/null
+++ b/pam_gdm/meson.build
@@ -0,0 +1,16 @@
+pam_gdm_deps = [
+  libpam_dep,
+]
+
+if keyutils_dep.found()
+  pam_gdm_deps += keyutils_dep
+endif
+
+pam_gdm = library('pam_gdm',
+  'pam_gdm.c',
+  dependencies: pam_gdm_deps,
+  include_directories: config_h_dir,
+  name_prefix: '',
+  install: true,
+  install_dir: pam_mod_dir,
+)
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 00000000..f904cde4
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1,3 @@
+i18n.gettext(meson.project_name(),
+  preset: 'glib'
+)
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 00000000..128b5d2e
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,17 @@
+m_common_test_src = [
+  'm-common.c',
+  's-common-address.c',
+  's-common.c',
+]
+
+m_common_test_deps = [
+  libgdmcommon_dep,
+  libcheck_dep,
+]
+
+m_common_test = executable('m-common',
+  m_common_test_src,
+  dependencies: m_common_test_deps,
+)
+
+test('m-common', m_common_test)
diff --git a/utils/meson.build b/utils/meson.build
new file mode 100644
index 00000000..ef5968b0
--- /dev/null
+++ b/utils/meson.build
@@ -0,0 +1,41 @@
+# gdm-flexiserver
+gdm_flexiserver_deps = [
+  glib_dep,
+  libgdmcommon_dep,
+]
+
+gdm_flexiserver = executable('gdm-flexiserver',
+  'gdmflexiserver.c',
+  dependencies: gdm_flexiserver_deps,
+  include_directories: config_h_dir,
+  install: true,
+)
+
+# gdm-screenshot
+gdm_screenshot_deps = [
+  glib_dep,
+  gtk_dep,
+  x_deps,
+  libcanberra_gtk_dep,
+]
+
+gdm_screenshot = executable('gdm-screenshot',
+  'gdm-screenshot.c',
+  dependencies: gdm_screenshot_deps,
+  include_directories: config_h_dir,
+  install: true,
+)
+
+# gdm-disable-wayland
+gdm_disable_wayland_deps = [
+  glib_dep,
+]
+
+gdm_disable_wayland = executable('gdm-disable-wayland',
+  'gdm-disable-wayland.c',
+  dependencies: gdm_disable_wayland_deps,
+  include_directories: config_h_dir,
+  install: true,
+  install_dir: get_option('libexecdir'),
+)
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]