summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peterson <mkp@src.gnome.org>1999-04-18 22:08:08 +0000
committerMartin Peterson <mkp@src.gnome.org>1999-04-18 22:08:08 +0000
commit48dfb0c6fc683eb0512074448bc4418ad8241e40 (patch)
treecf7b1a5029538937affbbfd917db176d524ed8f6
downloadgdm-48dfb0c6fc683eb0512074448bc4418ad8241e40.tar.gz
Initial revision
-rw-r--r--.cvsignore29
-rw-r--r--ABOUT-NLS226
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog672
-rw-r--r--Makefile.am4
-rw-r--r--NEWS0
-rw-r--r--README64
-rw-r--r--README.install23
-rw-r--r--TODO4
-rw-r--r--acconfig.h13
-rw-r--r--acinclude.m4389
-rwxr-xr-xautogen.sh17
-rw-r--r--config/.cvsignore7
-rwxr-xr-xconfig/:02
-rw-r--r--config/Default6
-rwxr-xr-xconfig/Gnome.in18
-rw-r--r--config/Makefile.am75
-rwxr-xr-xconfig/Xsession41
-rw-r--r--config/gdm8
-rw-r--r--config/gdm.conf.in60
-rw-r--r--config/gnomerc.in1
-rw-r--r--config/locale.alias54
-rw-r--r--configure.in108
-rw-r--r--daemon/.cvsignore5
-rw-r--r--daemon/Makefile.am30
-rw-r--r--daemon/auth.c157
-rw-r--r--daemon/cookie.c106
-rw-r--r--daemon/filecheck.c120
-rw-r--r--daemon/gdm.c626
-rw-r--r--daemon/gdm.h86
-rw-r--r--daemon/md5.c253
-rw-r--r--daemon/md5.h27
-rw-r--r--daemon/misc.c289
-rw-r--r--daemon/server.c317
-rw-r--r--daemon/slave.c615
-rw-r--r--daemon/verify.c271
-rw-r--r--daemon/xdmcp.c854
-rw-r--r--docs/Makefile.am8
-rw-r--r--docs/Makefile.in255
-rw-r--r--docs/gdm-manual.txt352
-rw-r--r--gdm.spec78
-rw-r--r--gui/Makefile.am25
-rw-r--r--gui/Makefile.in400
-rw-r--r--gui/gdmchooser.c676
-rw-r--r--gui/gdmchooser.h40
-rw-r--r--gui/gdmgreeter.c1713
-rw-r--r--gui/gdmgreeter.h35
-rw-r--r--gui/gdmlogin.c1133
-rw-r--r--pixmaps/.cvsignore2
-rw-r--r--pixmaps/Makefile.am8
-rw-r--r--pixmaps/gdm.xpm285
-rw-r--r--pixmaps/nophoto.pngbin0 -> 6407 bytes
-rw-r--r--po/.cvsignore9
-rw-r--r--po/ChangeLog4
-rw-r--r--po/Makefile.in.in248
-rw-r--r--po/POTFILES.in11
-rw-r--r--po/de.po865
-rw-r--r--po/es.po954
-rw-r--r--po/fr.po1012
-rw-r--r--po/no.po949
60 files changed, 14640 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 00000000..9d2ec3c7
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,29 @@
+Makefile
+Makefile.in
+aclocal.m4
+config.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+configure.scan
+libtool
+ltconfig
+ltmain.sh
+missing
+mkinstalldirs
+stamp-h.in
+stamp-h
+stamp.h
+install-sh
+confdefs.h
+INSTALL
+COPYING
+mkinstalldirs
+missing
+install-sh
+stamp-h.in
+stamp.h.in
diff --git a/ABOUT-NLS b/ABOUT-NLS
new file mode 100644
index 00000000..28d38c76
--- /dev/null
+++ b/ABOUT-NLS
@@ -0,0 +1,226 @@
+Notes on the Free Translation Project
+*************************************
+
+ Free software is going international! The Free Translation Project
+is a way to get maintainers of free software, translators, and users all
+together, so that will gradually become able to speak many languages.
+A few packages already provide translations for their messages.
+
+ If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site. But you do *not*
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+ Installers will find here some useful hints. These notes also
+explain how users should proceed for getting the programs to use the
+available translations. They tell how people wanting to contribute and
+work at translations should contact the appropriate team.
+
+ When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used. The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+One advise in advance
+=====================
+
+ If you want to exploit the full power of internationalization, you
+should configure it using
+
+ ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed. So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias or message inheritance) as the
+implementation here. It is also not possible to offer this additional
+functionality on top of a `catgets' implementation. Future versions of
+GNU `gettext' will very likely convey even more functionality. So it
+might be a good idea to change to GNU `gettext' as soon as possible.
+
+ So you need not provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+INSTALL Matters
+===============
+
+ Some packages are "localizable" when properly installed; the
+programs they contain can be made to speak your own native language.
+Most such packages use GNU `gettext'. Other packages have their own
+ways to internationalization, predating GNU `gettext'.
+
+ By default, this package will be installed to allow translation of
+messages. It will automatically detect whether the system provides
+usable `catgets' (if using this is selected by the installer) or
+`gettext' functions. If neither is available, the GNU `gettext' own
+library will be used. This library is wholly contained within this
+package, usually in the `intl/' subdirectory, so prior installation of
+the GNU `gettext' package is *not* required. Installers may use
+special options at configuration time for changing the default
+behaviour. The commands:
+
+ ./configure --with-included-gettext
+ ./configure --with-catgets
+ ./configure --disable-nls
+
+will respectively bypass any pre-existing `catgets' or `gettext' to use
+the internationalizing routines provided within this package, enable
+the use of the `catgets' functions (if found on the locale system), or
+else, *totally* disable translation of messages.
+
+ When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this. This might be not what is desirable. You
+should use the more recent version of the GNU `gettext' library. I.e.
+if the file `intl/VERSION' shows that the library which comes with this
+package is more recent, you should use
+
+ ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+ By default the configuration process will not test for the `catgets'
+function and therefore they will not be used. The reasons are already
+given above: the emulation on top of `catgets' cannot provide all the
+extensions provided by the GNU `gettext' library. If you nevertheless
+want to use the `catgets' functions use
+
+ ./configure --with-catgets
+
+to enable the test for `catgets' (this causes no harm if `catgets' is
+not available on your system). If you really select this option we
+would like to hear about the reasons because we cannot think of any
+good one ourself.
+
+ Internationalized packages have usually many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language. Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package. However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+Using This Package
+==================
+
+ As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+ISO 639 `LL' two-letter code prior to using the programs in the
+package. For example, let's suppose that you speak German. At the
+shell prompt, merely execute `setenv LANG de' (in `csh'),
+`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This
+can be done from your `.login' or `.profile' file, once and for all.
+
+ An operating system might already offer message localization for
+many of its programs, while other programs have been installed locally
+with the full capabilities of GNU `gettext'. Just using `gettext'
+extended syntax for `LANG' would break proper localization of already
+available operating system programs. In this case, users should set
+both `LANGUAGE' and `LANG' variables in their environment, as programs
+using GNU `gettext' give preference to `LANGUAGE'. For example, some
+Swedish users would rather read translations in German than English for
+when Swedish is not available. This is easily accomplished by setting
+`LANGUAGE' to `sv:de' while leaving `LANG' to `sv'.
+
+Translating Teams
+=================
+
+ For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list, courtesy of Linux
+International. You may reach your translation team at the address
+`LL@li.org', replacing LL by the two-letter ISO 639 code for your
+language. Language codes are *not* the same as the country codes given
+in ISO 3166. The following translation teams exist, as of December
+1997:
+
+ Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
+ Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
+ `hu', Irish `ga', Italian `it', Indonesian `id', Japanese `ja',
+ Korean `ko', Latin `la', Norwegian `no', Persian `fa', Polish
+ `pl', Portuguese `pt', Russian `ru', Slovenian `sl', Spanish `es',
+ Swedish `sv', and Turkish `tr'.
+
+For example, you may reach the Chinese translation team by writing to
+`zh@li.org'.
+
+ If you'd like to volunteer to *work* at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is *not* the same as the list itself, it has
+`-request' appended. For example, speakers of Swedish can send a
+message to `sv-request@li.org', having this message body:
+
+ subscribe
+
+ Keep in mind that team members are expected to participate
+*actively* in translations, or at solving translational difficulties,
+rather than merely lurking around. If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `translation@iro.umontreal.ca' to reach the
+coordinator for all translator teams.
+
+ The English team is special. It works at improving and uniformizing
+the terminology in use. Proven linguistic skill are praised more than
+programming skill, here.
+
+Available Packages
+==================
+
+ Languages are not equally supported in all packages. The following
+matrix shows the current state of internationalization, as of December
+1997. The matrix shows, in regard of each package, for which languages
+PO files have been submitted to translation coordination.
+
+ Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ .----------------------------------------------------.
+ bash | [] [] [] | 3
+ bison | [] [] [] | 3
+ clisp | [] [] [] [] | 4
+ cpio | [] [] [] [] [] [] | 6
+ diffutils | [] [] [] [] [] | 5
+ enscript | [] [] [] [] [] [] | 6
+ fileutils | [] [] [] [] [] [] [] [] [] [] | 10
+ findutils | [] [] [] [] [] [] [] [] [] | 9
+ flex | [] [] [] [] | 4
+ gcal | [] [] [] [] [] | 5
+ gettext | [] [] [] [] [] [] [] [] [] [] [] | 12
+ grep | [] [] [] [] [] [] [] [] [] [] | 10
+ hello | [] [] [] [] [] [] [] [] [] [] [] | 11
+ id-utils | [] [] [] | 3
+ indent | [] [] [] [] [] | 5
+ libc | [] [] [] [] [] [] [] | 7
+ m4 | [] [] [] [] [] [] | 6
+ make | [] [] [] [] [] [] | 6
+ music | [] [] | 2
+ ptx | [] [] [] [] [] [] [] [] | 8
+ recode | [] [] [] [] [] [] [] [] [] | 9
+ sh-utils | [] [] [] [] [] [] [] [] | 8
+ sharutils | [] [] [] [] [] [] | 6
+ tar | [] [] [] [] [] [] [] [] [] [] [] | 11
+ texinfo | [] [] [] | 3
+ textutils | [] [] [] [] [] [] [] [] [] | 9
+ wdiff | [] [] [] [] [] [] [] [] | 8
+ `----------------------------------------------------'
+ 17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ 27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179
+
+ Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect. This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+ For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer. There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+ If December 1997 seems to be old, you may fetch a more recent copy
+of this `ABOUT-NLS' file on most GNU archive sites.
+
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 00000000..7c7f47a8
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Martin Kasper Petersen <mkp@SunSITE.auc.dk>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 00000000..81550a68
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,672 @@
+1999-03-28 Martin Kasper Petersen <mkp@mkp.net>
+
+ * gui/gdmgreeter.c (gdm_greeter_user_alloc): Icon size bug
+ reported by Clifford Wright.
+
+1999-03-07 Martin Kasper Petersen <mkp@mkp.net>
+
+ * configure.in, src/Makefile.am: Pass -DGDM_CONFIG_PATH to
+ compiler to avoid ${prefix}/blah bug in Owen's patch.
+
+1999-03-06 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_user_alloc): Fixed a memory
+ corruption bug (Reported by Centove).
+
+1999-03-05 Martin Kasper Petersen <mkp@mkp.net>
+
+ * gdm.spec: Fix spec file.
+
+ * Misc fixes.
+
+1999-03-03 Martin Kasper Petersen <mkp@mkp.net>
+
+ * config/Makefile.am, configure.in: Patch from Owen.
+
+ * po/de.po: Added (Patch from Karsten Weiss
+ <karsten@addx.au.s.shuttle.de>).
+
+1999-02-26 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (main): Force completion mode on for the time
+ being. I'll implement a real PAM conversation function within the
+ next couple of days to take care of the exposed usernames issue.
+
+1999-02-25 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmchooser.c: Done!
+
+ * src/gdmchooser.c: First shot at reimplementing the code I
+ lost. Doesn't actually work yet.
+
+1999-02-24 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmxdmcp.c: Fix gethostbyaddr() lookups.
+
+ * src/gdmslave.c: Various fixes.
+
+ * src/gdm.c (gdm_display_dispose): Call XCloseDisplay to close
+ remote connections.
+
+ (gdm_child_handler): Fix wrong debug output.
+
+ * config/Makefile.am: Create Default display init file.
+
+1999-02-23 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmverify.c (gdm_verify_user): Added shadow support (Patch
+ from Timo Sirainen).
+
+ * src/gdmgreeter.c (main): Added GtkRC support
+ (Patch from Daniel_Burrows@brown.edu).
+
+1999-02-23 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdmgreeter.c (main): Call gnome sound shutdown here.
+
+ * src/gdm.c (main): Show a descriptive message to let the user
+ locate the stale pid file.
+
+ * configure.in (LIBWRAP_PATH): Use the same configuration
+ mechanism for detecting a working libwrap library on the system
+ (fixes crash).
+
+ * src/gdmslave.c (gdm_slave_greeter): Do not use sscanf to get the
+ password, as it might contain spaces, just copy the string.
+ (gdm_slave_get_opts): Use fgets directly on the target buffer.
+ (gdm_slave_get_opts): Make the strings empty at startup.
+
+ * src/gdmgreeter.c (gdm_greeter_logo_init): Use gnome-pixmap
+ widget instead of gtk-pixmap. Gnome-pixmap correctly uses the
+ right visual and is simpler to use (and does not crash on
+ multidepth visuals).
+ (gdm_greeter_iconify_handler): Use gnome-pixmao here too.
+
+1999-02-16 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdm.c: Ignore invalid lines in [servers] section.
+
+1999-02-14 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmserver.c: Changed SA_ONESHOT to SA_RESETHAND.
+
+1999-02-08 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_parse_config): Disable shutdown
+ menu on non-local displays.
+
+ * src/gdm.c (gdm_config_parse): Default path belongs in
+ [system] (msw).
+
+ * src/gdmxdmcp.c (gdm_xdmcp_init): Use GIOChannel to monitor fds.
+
+ * src/gdmmisc.c (gdm_parse_enriched_string): Support %d expansion
+ for display name.
+
+1999-02-06 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmxdmcp.c (gdm_xdmcp_send_accept): MIT cookies work for
+ remote displays now.
+
+ * src/gdmslave.c: Lots of fixes. Should be stable again.
+
+1999-02-04 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_child_handler): Only xping remote
+ displays to avoid DISPLAY_ABORT for murdered greeters/Xservers.
+
+ * src/gdmmisc.c (gdm_exec_script): Set default path before
+ executing.
+
+1999-02-03 Martin Kasper Petersen <mkp@mkp.net>
+
+ * Makefile.am: Stuff the docs dir back in and add the appropriate
+ Makefile.am.
+
+1999-02-02 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c: Fixes for XDMCP vs. local display handling.
+
+ * src/gdmxdmcp.c: Numerous fixes.
+
+1999-01-31 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmxdmcp.c: First shot at XDMCP implentation.
+
+1999-01-28 Martin Kasper Petersen <mkp@mkp.net>
+
+ * configure.in/Makefile.am: Generate Makefile in docs. Added
+ README.install to EXTRA_DIST.
+
+1999-01-27 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_info): Fixed the annoying hanging
+ Gtk bug caused by my inability to program user interfaces. Ahem.
+
+ * configure.in: Stuff GNOME_GETTEXT back in.
+
+1999-01-25 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_session_start): Moved english->C
+ locale here. Ugly, but it became a mess in greeter too.
+
+ * src/gdmverify.c (gdm_verify_user): Repetetetive pam_setcred
+ spotted by gb. Fixed.
+
+1999-01-22 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmverify.c (gdm_verify_user): syslog ident workaround.
+
+ * src/gdmgreeter.c (gdm_greeter_session_init): Used widget pointer
+ as session name if no default was found. Fixed.
+
+ * src/gdm.c (gdm_display_unmanage): Avoid killing master daemon
+ when unmanaging displays.
+
+ * src/gdmslave.c (gdm_slave_session_start): Added call to
+ initgroups() to set up additional group memberships.
+
+ * src/gdmverify.c (gdm_verify_user): Fix non-PAM password
+ checking.
+
+1999-01-20 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmverify.c (gdm_verify_user): Updated PAM stuff.
+
+1999-01-19 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdmslave.c (gdm_slave_session_start): Set the umask.
+
+1999-01-19 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmverify.c (gdm_verify_pam_conv): Quick workaround for PAM
+ stuff. Real solution due tomorrow.
+
+ * src/gdmgreeter.c: Lots of new stuff. Non completion mode
+ deprecated. On demand NFS lookups. Language selection.
+
+ * src/gdmslave.c (gdm_slave_greeter): New session/language
+ selection support.
+
+1999-01-18 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_session_start): Fixed memleak.
+
+1999-01-15 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdmslave.c (gdm_slave_greeter): Check return values from
+ sscanf. Because "\n" scanned with %s returns -1 and the target
+ buffer has an undefined value.
+
+ * src/gdm.c (main): Set the umask to 066 to make any
+ default file created indirectly by gnome-config be of mode 066.
+
+1999-01-13 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_sessions_init): Check that Session
+ scripts are executable before adding them to the list.
+
+ * src/gdmmisc.c (gdm_file_check): Added an option making the
+ function return TRUE if it is ok that a file is absent. I.e. the
+ user has no existing .Xauthority, .gnome/gdm or whatever.
+
+ * src/gdmslave.c (gdm_slave_session_start): Added default
+ path. Create ~user/.gnome if it doesn't exist.
+
+ * src/gdmslave.c (gdm_slave_session_stop): More setegid().
+
+ * src/gdmslave.c (gdm_slave_session_start): Added setgid().
+ (gdm_slave_greeter): Fixed sigmask.
+
+ * src/gdmauth.c (gdm_auth_user_{add|remove}): Added -i to xauth to
+ ignore hanging locks.
+
+ * src/gdmgreeter.c (main): Resize only when browser is enabled.
+
+ * src/gdmgreeter.c (gdm_greeter_message_init): Removed debug msg.
+
+ * src/gdm.c (gdm_config_parse): Bail out if gdm user/group doesn't
+ exist. Root failover made people lazy.
+
+ * src/gdm.c (gdm_child_handler): Minor fix to make gdm work with
+ more than one local Xserver.
+
+1999-01-12 Martin Kasper Petersen <mkp@mkp.net>
+
+ * config/gdm.conf.in ([system]): Added UserIconMax{Width,Height}.
+
+ * src/gdmgreeter.c (gdm_greeter_user_alloc): Scales user icons to
+ sysadmin specified max size.
+
+ * src/gdmgreeter.c (gdm_greeter_iconify_handler): Fixed
+ iconification bug.
+
+ (gdm_greeter_login_key_handler): Cursor/Tab key restriction.
+
+ * src/gdmslave.c (gdm_slave_greeter): Forgot to setgid()
+
+ (gdm_slave_greeter): Workaround for getenv("HOME") until miguel
+ fixes gnome_init().
+
+ * src/gdmmisc.c (gdm_parse_enriched_string): Fallback if
+ getenv("HOSTNAME")==NULL.
+
+1999-01-11 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/<younameit>.[ch] Done rewriting the daemon code to avoid the
+ race condition caused by simultaneous greeter/session and Xserver
+ death.
+
+1998-12-30 Jeff Garzik <jgarzik@pobox.com>
+
+ * src/gdmauth.c, src/gdmgreeter.c, src/gdmmisc.c,
+ src/gdmslave.c, src/gdmxdmcp.c:
+ s/g_copy_strings/g_strconcat/
+
+1998-12-28 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/*.c: Loads of fixes over the past couple of days.
+
+ * src/gdmgreeter.c (gdm_greeter_parse_config): gdmUserMaxFile
+ tunable.
+
+ * src/gdmmisc.c (gdm_file_check): Moved gdm_greeter_file_check
+ here. Now a generic function.
+
+ * src/gdmslave.c (gdm_slave_windows_kill_error_handler): Ok,
+ nailed down the bug which caused gdmslave to exit(1)
+ mysteriously. A race in the windows_recursive_kill function caused
+ the X default error handler to kick in. Blam. You're dead.
+
+ (gdm_slave_session_init): Run sanity check on ~user/.Xauthority
+ and ~user/.gnome/gdm.
+
+ (gdm_slave_exec_command): Use the passed pointer instead of
+ gdmSuspend.
+
+ (gdm_slave_session_init): Added SHELL environment variable so the
+ user's shell is executed. Not just root's..
+
+1998-12-25 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_user_alloc): Rewritten to use
+ sanity check.
+
+ (gdm_greeter_file_check): New function. Checks file size,
+ ownership etc. to avoid DoS attacks on greeter.
+
+1998-12-23 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdm.c (gdm_abort): New function for error logging and
+ aborting.
+
+ (gdm_config_parse): luser proof permissions checking on authdir.
+
+ * src/gdmgreeter.c: Several oddities fixed.
+
+ * src/gdmgreeter.c (gdm_greeter_buttons_init): Mark login button
+ as default.
+
+ * src/gdmgreeter.c (gdm_greeter_login_entry_handler): Fixed event
+ handlers to avoid the obscure emit_stop bug. Turns out my ancient
+ event handlers were doing the right thing all along. Only the
+ recent ones were br0ked. *sigh*. Thanks Owen!
+
+1998-12-22 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_greet_init): Removed debug logging of
+ username and password. Ahem. Thanks Sopwith!
+
+ * src/gdmgreeter.c (gdm_greeter_login_entry_handler):
+ Fixes. gtk_signal_emit_stop_by_name workaround.
+
+1998-12-20 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_invalid_passwd_req): Minor hack to
+ avoid greeter to be reactivated during dialog.
+
+ * src/(gdm_greeter_entry_init): Limit input length in login and
+ password entry fields.
+
+ * src/gdmslave.c (gdm_slave_greet_init): Avoid potential buffer
+ overflow, in case something/someone breaks greeter.
+
+1998-12-15 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmverify.c (gdm_verify_user): Two buglets reported by
+ <kvajk@ricochet.net>.
+
+1998-12-14 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_browser_unselect): Catch
+ BUTTON_RELEASE.
+
+1998-12-13 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_{reboot,halt}_handler): Use
+ gnome_question_dialog instead of message_box.
+
+1998-12-03 Martin Kasper Petersen <mkp@mkp.net>
+
+ * config/Makefile.am: Fixed gnomerc. Both path and INSTALL_SCRIPT
+ were wrong -- No wonder people have been complaining. *sigh*
+
+ * src/gdm.c (main): Abort with (xdm compliant :) error message if
+ gdm isn't started by root.
+
+1998-12-01 Martin Kasper Petersen <mkp@mkp.net>
+
+ * docs/gdm-manual.txt: Crude manual draft.
+
+ * src/gdm.c, config/gdm.conf.in: The PreRoot and PostRoot
+ directories have been renamed PreSession and PostSession to avoid
+ confusion.
+
+1998-11-30 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_message_init): Calls the enriched
+ string function on the message string to support ``Welcome to
+ <hostname>''. Need to supply both server and client macros.
+
+ * src/gdmmisc.c (gdm_parse_enriched_string): New function for %h
+ expansion in strings.
+
+ * src/gdmgreeter.c: Removed legacy labels and such. gettext takes
+ it from here.
+
+ * src/gdm.c (gdm_config_parse): Check for correct permissions on
+ vardir.
+
+1998-11-29 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdmgreeter.c (gdm_greeter_browser_init): IconList now starts
+ life in thawed mode.
+
+1998-11-22 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_browser_select): Reverted to the
+ old event types (GDK_BUTTON_PRESS) for gnome-icon-list.
+
+ * src/gdmslave.c, src/gdmgreeter.c, src/gdm.c: Added support for
+ suspending APM-aware machines from greeter.
+
+1998-11-20 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c: Fixed X server restart stuff. gdmslave rewrite
+ done.
+
+ * src/gdmslave.c, src/gdm.c, config/gdm.conf.in: Implemented
+ KillInitClients option (Requested by sct).
+
+1998-11-18 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_display_init): Finally nailed down the
+ bug that has been haunting me for the past week causing
+ gdm_slave_windows_kill to hang on second login. The X server takes
+ a while to recover consciousness after a reset. I take this into
+ account by sleeping for a while if XOpenDisplay fails.
+ Unfortunately, dsp was already initialized in second run
+ (but invalid after the X server reset) causing my retry condition
+ to be ignored. Always check your pointers! *sigh*
+
+ So, the new gdm should be as fast as xdm (i.e. fewer resets
+ causing garbled displays and momentary flicker. Visual annoyances
+ beyond this point - Go bug the X server people).
+
+ SANE tutorial coming up in 6 hours. *Thud*
+
+1998-11-09 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c More or less a rewrite.
+
+1998-11-08 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_init): Add d->name when starting X
+ server.
+
+ * src/gdm.c (gdm_config_parse): Added intelligent AuthDir
+ searching and gdmLogDir. gdmLogFile deprecated.
+
+ * src/gdmslave.c (gdm_slave_init): Moved stdout, stderr logging
+ here. Logs are now per-display.
+
+1998-11-08 Martin Kasper Petersen <mkp@mkp.net>
+
+ * #include<errno.h> in *.c.
+
+1998-11-02 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_session_init): Reset display instead
+ of restarting the X server every time.
+
+1998-11-01 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_session_init): If PreRoot script
+ returns > 0 abort session.
+
+1998-10-31 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmauth.c (gdm_auth_user_add): New function.
+ (gdm_auth_user_remove): New function. ~/.Xauthority management.
+
+1998-10-30 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmmisc.c (gdm_arg_munch): Zero out the remaining
+ argv-entries. We use the static array several times.
+
+ * src/gdmslave.c (gdm_slave_session_init): Removed malloc(pwent) -
+ Duh!.
+
+ * src/gdm.c (gdm_config_parse): Added group lookup. Removed
+ malloc(pwent).
+
+1998-10-26 Martin Kasper Petersen <mkp@mkp.net>
+
+ * config/gdm.conf.in: New User and Group keys override NobodyUser
+
+1998-10-21 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdm.c (gdm_restart_slave): Implemented reboot and halt.
+
+ * src/gdmverify.c: #ifdefs to make it compile on non PAM systems.
+
+ * src/Makefile.am (gdm_SOURCES): Added gdmmisc.c
+
+ * src/gdmmisc.c: Moved arg_much to a seperate file. It is now used
+ by both gdm.c and gdmslave.c.
+
+1998-10-20 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c: Send STX through pipeline before sending a
+ command.
+
+ * src/gdmslave.c (gdm_slave_display_init): Added STX for greeter
+ communications to avoid problems with Gtk debug errors to stdout.
+
+1998-10-19 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_browser_init): Added background
+ color in browser.
+
+ * src/gdmgreeter.c (gdm_greeter_browser_select): Change
+ GDK_BUTTON_PRESS to ditto RELEASE due to gil.
+
+ * src/gdmgreeter.c (main): Removed buggy icon list workaround.
+ (main): Center window before realizing it.
+ (gdm_greeter_browser_init): Added 3D frame to new icon list.
+
+1998-10-18 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdmgreeter.c (gdm_greeter_browser_init): Icon List is born
+ in frozen state, calling freeze and thaw leaves it still in frozen
+ state (as we have a frozen counter instead of a flag these days.).
+
+1998-10-16 Christopher Blizzard <blizzard@appliedtheory.com>
+
+ * config/Makefile.am (install-data-hook): Make sure that
+ install-data-hook depends on targets gdm.conf gnomerc and Gnome.
+ Otherwise they are never built. Also, if the directories that
+ these files are supposed to go in don't exist, create them with
+ the proper mode.
+
+1998-10-13 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdmgreeter.c (gdm_greeter_login_entry_handler): Fix use of
+ the gnome_icon_list_moveto routine
+ (gdm_greeter_browser_update): ditto.
+ (gdm_greeter_browser_init): Adapt to the new gnome-icon-list api.
+ (gdm_greeter_login_entry_handler): Thaw before attempting to use moveto
+
+ Martin, is there any reason why you clear() the icon lists
+ contents and then reload them when the user changes from the login
+ field to the password one?
+
+1998-10-13 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_exec_script): New function.
+ (gdm_slave_display_init): Add support for display init script.
+ (gdm_slave_session_init): Add support for root pre-login script.
+ (gdm_slave_session_init): Add support for root post-login script.
+
+ * src/gdm.c (gdm_config_parse): Added new config options for
+ scripts.
+
+ * config/gdm.conf.in ([daemon]): Default config options for
+ scripts.
+
+1998-10-11 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdm.c (main): Redirect all output to a logfile.
+
+ * src/gdm.c (main): Moved the pid checking code to main to avoid
+ /sbin/init respawns. Checks whether gdm is started by init and
+ stops forking if this is the case (actually works this time).
+
+ * config/gdm.conf.in (PidFile): I've been ignoring all bug reports
+ caused by this one. Turns out I made a typo in the config template
+ file. *sigh*
+
+1998-10-11 Carsten Schaar <nhadcasc@fs-maphy.uni-hannover.de>
+
+ * src/Makefile.am (gdm_LDADD): Added '$(INTLLIBS).
+ (gdmgreeter_LDADD): Likewise.
+
+1998-10-10 Martin Kasper Petersen <mkp@mkp.net>
+
+ * config/gdm.conf.in ([servers]): Modified to default X server
+ entry to exclude display depth option.
+
+ * config/Makefile.am (install-data-hook): Avoid overwriting
+ existing config files.
+
+ * acconfig.h: Added HAVE_PAM
+
+ * src/gdmverify.c (gdm_verify_user): Change USE_PAM to HAVE_PAM to
+ follow conventions.
+
+ * configure.in (have_pam): PAM autodetection.
+
+1998-10-08 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_invalid_passwd_req): Set focus to
+ passwd field when auth fails.
+
+ * src/gdmslave.c: Finished the rewrite. Should be almost usable
+ again.
+
+ * config/Makefile.am: TODO: Need to find a way to prevent
+ overwriting gdm.conf when doing a make install.
+
+1998-10-07 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_login): Completely new
+ communication scheme. Easier to parse in gdmslave.c.
+
+1998-10-06 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmverify.c: New file. TODO: PAM detection in autoconf.
+
+ * src/gdmslave.c: Gave up on merging CVS and my .ch-work. Started
+ major rewrite instead.
+
+ * src/gdmgreeter.c: Removed `:' in pipe communication
+ protocol. Waste.
+
+1998-10-05 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c: Fixed the race reported on gnome-list the right
+ way. The posted fix broke X USR1 signalling.
+
+ * src/gdmgreeter.c (gdm_greeter_about): Bumped version
+ number. Whee.
+ (gdm_greeter_done): New function. Partly replaces parse_results().
+ (gdm_greeter_login): Former login_button_handler. Now passes
+ password through pipe. Disables input while gdmslave is thinking.
+ (gdm_greeter_passwd_entry_handler): Replaced parse_results with
+ gdm_greeter_login to reflect the auth redesign.
+ (gdm_greeter_invalid_passwd_req): Re-enable input and reset cursor
+ after requester has been acked.
+ (main): Added signal handling for gdmslave communication.
+
+1998-10-04 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdm.c: signal->sigaction stuff.
+ (gdm_daemonify): Moved openlog to main.
+ (main): Stop forking when ppid is init.
+
+1998-10-01 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdmslave.c (gdm_slave_init): Setup the signal before
+ forking. FIXME: We need to use sigaction all over the place
+ instead of signal.
+
+Thu Sep 24 22:09:39 CEST 1998 Jochen Friedrich <jochen@scram.de>
+
+ * src/gdmgreeter.c: Fixed a memory corruption.
+
+1998-09-15 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmslave.c (gdm_slave_usr1_handler): Added support for
+ setting last session in ~/.gnome/gdm/session/last. I had forgotten
+ all about it after I removed it from greeter.
+
+ * src/gdm.c Gazillions of fixes
+
+ * src/gdmslave.c Gazillions of fixes
+
+1998-09-14 Martin Kasper Petersen <mkp@mkp.net>
+
+ * src/gdmgreeter.c (gdm_greeter_verify_user): Replaced annoying
+ LOG_AUTH with LOG_ERR.
+
+ * config/Makefile.am: Changed _DATA to _SCRIPTS for gnomerc et al.
+
+1998-09-10 Miguel de Icaza <miguel@nuclecu.unam.mx>
+
+ * src/gdm.c (gdm_config_parse): Simplify as well.
+
+ * src/gdmgreeter.c (gdm_greeter_user_alloc): Fix my oversimplication
+ from last night.
+
+ * src/gdmgreeter.c (gdm_greeter_user_alloc): More simplification
+ of the use of gnome-config. I think I really should document it.
+
+ * src/gdm.h (gdm_slave_init): Add prototype. Remove include to
+ gnome.h.
+
+ * src/gdmslave.c (gdm_slave_usr1_handler): Log errors when the
+ session can not be launched.
+ Simplify the includes.
+
+ * src/gdmgreeter.c (gdm_greeter_parse_config): Simplify the code
+ by using gnome_config_push_prefix
+ (gdm_greeter_parse_config): Do not strdup the resulting strings,
+ they are already dupped
+ (gdm_greeter_sessions_init): Removed dependency on static buffer
+ for s. Find correcly the default session.
+
+Tue Sep 8 16:11:49 EDT 1998 Gregory McLean
+
+ * acconfig.h : added this file so one can cvs -z3 co gdm, cd gdm
+ ./autogen.sh; make and have an executable be spit out.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 00000000..1845ca8e
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,4 @@
+SUBDIRS = config macros pixmaps gui daemon docs intl po
+
+EXTRA_DIST = ChangeLog README.install gdm.spec
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 00000000..1533456b
--- /dev/null
+++ b/README
@@ -0,0 +1,64 @@
+
+
+ GDM - GNOME DISPLAY MANAGER
+
+
+The Gnome Display Manager is a re-implementation of the well known xdm
+program. gdm consists of four separate parts: A small daemon, two
+slightly different graphical login programs and a host chooser.
+
+gdm 2.0 implements all significant features required for managing
+local and remote displays.
+
+gdm daemon:
+
+ o X Authentication
+ o Default and per-display initialization scripts
+ o Pre and post session scripts
+ o Pluggable Authentication Modules
+ o XDMCP
+ o TCP Wrappers for access control
+
+gdmgreeter:
+
+ o Logo image (in any GdkImlib supported format)
+ o A face browser like the one on NeXT/SGI
+ o Tab-completion (no, doesn't work on passwords)
+ o Halt, reboot and laptop suspend
+ o Iconified login window (i.e. for xfishtank)
+ o Session selection support (Package manager friendly)
+ o Language selection support
+
+gdmlogin:
+
+ o Logo image
+ o Halt and reboot
+ o Iconified login window
+ o Session selection support
+ o Language selection support
+
+gdmchooser:
+
+ o Visual host browser
+ o Customizable icons
+
+
+Most features can be turned on and off in the configuration file by
+the sysadmin.
+
+Availability:
+
+ ftp://ftp.gnome.org/pub/GNOME/sources/gdm/
+
+
+Please consult README.install for instructions on how to configure and
+install gdm.
+
+Send suggestions, patches, bug reports etc. to mkp@SunSITE.auc.dk.
+Bear in mind that this is beta software and please enable debug
+logging (see README.install) and include your syslog and
+<vardir>/gdm/<display>.log when sending bug reports.
+
+
+Martin K. Petersen, The Gnome Project
+
diff --git a/README.install b/README.install
new file mode 100644
index 00000000..fd07aeec
--- /dev/null
+++ b/README.install
@@ -0,0 +1,23 @@
+QUICK NOTES ON INSTALLATION/USE:
+
+For security reasons a dedicated group id is needed for proper
+operation! gdm assumes that the group is called `gdm'. Furthermore gdm
+relies on the existence of a `nobody' user. Create these before
+running make install.
+
+You should run ``make install'' as root to get the permissions right
+on the authentication directory.
+
+Configuration is done by editing the gdm.conf file (located in
+<prefix>/etc/gdm/gdm.conf). If no config file exists, make install
+will create one for you.
+
+Put your (jpg, gif, png, xpm) picture in ~/.gnome/photo to make it
+appear in the face browser.
+
+When reporting bugs you should first turn on debugging in
+gdm.conf. Your syslog daemon might not log debug information per
+default so you should make sure daemon.debug events are logged to a
+file. Include the resulting log in your bug report.
+
+
diff --git a/TODO b/TODO
new file mode 100644
index 00000000..9b174220
--- /dev/null
+++ b/TODO
@@ -0,0 +1,4 @@
+WORK IN PROGRESS:
+
+ o Picon capplet for selecting the bitmap to appear in the browser.
+ o gdmconfig - a program for configuring the gdm.conf file.
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 00000000..ede6d248
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,13 @@
+#undef PACKAGE
+#undef VERSION
+#undef HAVE_LIBSM
+#undef GDM_XAUTH_PATH
+#undef ENABLE_NLS
+#undef HAVE_CATGETS
+#undef HAVE_GETTEXT
+#undef HAVE_LC_MESSAGES
+#undef HAVE_STPCPY
+#undef HAVE_PAM
+#undef HAVE_TCPWRAPPERS
+#undef HAVE_SHADOW
+
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 00000000..0655ccda
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,389 @@
+
+######################################################################
+# progtest.m4 from gettext 0.32
+######################################################################
+# Search path for a program which passes the given test.
+# Ulrich Drepper <drepper@cygnus.com>, 1996.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AM_PATH_PROG_WITH_TEST,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+ /*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in ifelse([$5], , $PATH, [$5]); do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if [$3]; then
+ ac_cv_path_$1="$ac_dir/$ac_word"
+ break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+ AC_MSG_RESULT([$]$1)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+
+######################################################################
+# lcmessage.m4 from gettext 0.32
+######################################################################
+# Check whether LC_MESSAGES is available in <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 1
+
+AC_DEFUN(AM_LC_MESSAGES,
+ [if test $ac_cv_header_locale_h = yes; then
+ AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+ [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+ am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ AC_DEFINE(HAVE_LC_MESSAGES)
+ fi
+ fi])
+
+
+
+######################################################################
+# gettext.m4 from gettext 0.32
+######################################################################
+# Macro to add for using GNU gettext.
+# Ulrich Drepper <drepper@cygnus.com>, 1995.
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+# serial 3
+
+AC_DEFUN(AM_WITH_NLS,
+ [AC_MSG_CHECKING([whether NLS is requested])
+ dnl Default is enabled NLS
+ AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+ AC_MSG_RESULT($USE_NLS)
+ AC_SUBST(USE_NLS)
+
+ USE_INCLUDED_LIBINTL=no
+
+ dnl If we use NLS figure out what method
+ if test "$USE_NLS" = "yes"; then
+ AC_DEFINE(ENABLE_NLS)
+ AC_MSG_CHECKING([whether included gettext is requested])
+ AC_ARG_WITH(included-gettext,
+ [ --with-included-gettext use the GNU gettext library included here],
+ nls_cv_force_use_gnu_gettext=$withval,
+ nls_cv_force_use_gnu_gettext=no)
+ AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ dnl User does not insist on using GNU NLS library. Figure out what
+ dnl to use. If gettext or catgets are available (in this order) we
+ dnl use this. Else we have to fall back to GNU NLS library.
+ dnl catgets is only used if permitted by option --with-catgets.
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+ CATOBJEXT=NONE
+
+ AC_CHECK_HEADER(libintl.h,
+ [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
+ [AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
+ gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
+
+ if test "$gt_cv_func_gettext_libc" != "yes"; then
+ AC_CHECK_LIB(intl, bindtextdomain,
+ [AC_CACHE_CHECK([for gettext in libintl],
+ gt_cv_func_gettext_libintl,
+ [AC_TRY_LINK([], [return (int) gettext ("")],
+ gt_cv_func_gettext_libintl=yes,
+ gt_cv_func_gettext_libintl=no)])])
+ fi
+
+ if test "$gt_cv_func_gettext_libc" = "yes" \
+ || test "$gt_cv_func_gettext_libintl" = "yes"; then
+ AC_DEFINE(HAVE_GETTEXT)
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
+ if test "$MSGFMT" != "no"; then
+ AC_CHECK_FUNCS(dcgettext)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr],
+ [CATOBJEXT=.gmo
+ DATADIRNAME=share],
+ [CATOBJEXT=.mo
+ DATADIRNAME=lib])
+ INSTOBJEXT=.mo
+ fi
+ fi
+ ])
+
+ if test "$CATOBJEXT" = "NONE"; then
+ AC_MSG_CHECKING([whether catgets can be used])
+ AC_ARG_WITH(catgets,
+ [ --with-catgets use catgets functions if available],
+ nls_cv_use_catgets=$withval, nls_cv_use_catgets=no)
+ AC_MSG_RESULT($nls_cv_use_catgets)
+
+ if test "$nls_cv_use_catgets" = "yes"; then
+ dnl No gettext in C library. Try catgets next.
+ AC_CHECK_LIB(i, main)
+ AC_CHECK_FUNC(catgets,
+ [AC_DEFINE(HAVE_CATGETS)
+ INTLOBJS="\$(CATOBJS)"
+ AC_PATH_PROG(GENCAT, gencat, no)dnl
+ if test "$GENCAT" != "no"; then
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, no)
+ if test "$GMSGFMT" = "no"; then
+ AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)
+ fi
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.cat
+ INSTOBJEXT=.cat
+ DATADIRNAME=lib
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi])
+ fi
+ fi
+
+ if test "$CATOBJEXT" = "NONE"; then
+ dnl Neither gettext nor catgets in included in the C library.
+ dnl Fall back on GNU gettext library.
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ dnl Mark actions used to generate GNU NLS library.
+ INTLOBJS="\$(GETTOBJS)"
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
+ AC_SUBST(MSGFMT)
+ USE_INCLUDED_LIBINTL=yes
+ CATOBJEXT=.gmo
+ INSTOBJEXT=.mo
+ DATADIRNAME=share
+ INTLDEPS='$(top_builddir)/intl/libintl.a'
+ INTLLIBS=$INTLDEPS
+ LIBS=`echo $LIBS | sed -e 's/-lintl//'`
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+
+ dnl Test whether we really found GNU xgettext.
+ if test "$XGETTEXT" != ":"; then
+ dnl If it is no GNU xgettext we define it as : so that the
+ dnl Makefiles still can work.
+ if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
+ : ;
+ else
+ AC_MSG_RESULT(
+ [found xgettext programs is not GNU xgettext; ignore it])
+ XGETTEXT=":"
+ fi
+ fi
+
+ # We need to process the po/ directory.
+ POSUB=po
+ else
+ DATADIRNAME=share
+ nls_cv_header_intl=intl/libintl.h
+ nls_cv_header_libgt=intl/libgettext.h
+ fi
+
+ # If this is used in GNU gettext we have to set USE_NLS to `yes'
+ # because some of the sources are only built for this goal.
+ if test "$PACKAGE" = gettext; then
+ USE_NLS=yes
+ USE_INCLUDED_LIBINTL=yes
+ fi
+
+ dnl These rules are solely for the distribution goal. While doing this
+ dnl we only have to keep exactly one list of the available catalogs
+ dnl in configure.in.
+ for lang in $ALL_LINGUAS; do
+ GMOFILES="$GMOFILES $lang.gmo"
+ POFILES="$POFILES $lang.po"
+ done
+
+ dnl Make all variables we use known to autoconf.
+ AC_SUBST(USE_INCLUDED_LIBINTL)
+ AC_SUBST(CATALOGS)
+ AC_SUBST(CATOBJEXT)
+ AC_SUBST(DATADIRNAME)
+ AC_SUBST(GMOFILES)
+ AC_SUBST(INSTOBJEXT)
+ AC_SUBST(INTLDEPS)
+ AC_SUBST(INTLLIBS)
+ AC_SUBST(INTLOBJS)
+ AC_SUBST(POFILES)
+ AC_SUBST(POSUB)
+ ])
+
+AC_DEFUN(AM_GNU_GETTEXT,
+ [AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_RANLIB])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+ AC_REQUIRE([AC_C_CONST])dnl
+ AC_REQUIRE([AC_C_INLINE])dnl
+ AC_REQUIRE([AC_TYPE_OFF_T])dnl
+ AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+ AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+ AC_REQUIRE([AC_FUNC_MMAP])dnl
+
+ AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
+unistd.h values.h sys/param.h])
+ AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
+__argz_count __argz_stringify __argz_next])
+
+ if test "${ac_cv_func_stpcpy+set}" != "set"; then
+ AC_CHECK_FUNCS(stpcpy)
+ fi
+ if test "${ac_cv_func_stpcpy}" = "yes"; then
+ AC_DEFINE(HAVE_STPCPY)
+ fi
+
+ AM_LC_MESSAGES
+ AM_WITH_NLS
+
+ if test "x$CATOBJEXT" != "x"; then
+ if test "x$ALL_LINGUAS" = "x"; then
+ LINGUAS=
+ else
+ AC_MSG_CHECKING(for catalogs to be installed)
+ NEW_LINGUAS=
+ for lang in ${LINGUAS=$ALL_LINGUAS}; do
+ case "$ALL_LINGUAS" in
+ *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
+ esac
+ done
+ LINGUAS=$NEW_LINGUAS
+ AC_MSG_RESULT($LINGUAS)
+ fi
+
+ dnl Construct list of names of catalog files to be constructed.
+ if test -n "$LINGUAS"; then
+ for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
+ fi
+ fi
+
+ dnl The reference to <locale.h> in the installed <libintl.h> file
+ dnl must be resolved because we cannot expect the users of this
+ dnl to define HAVE_LOCALE_H.
+ if test $ac_cv_header_locale_h = yes; then
+ INCLUDE_LOCALE_H="#include <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. Take care yourself. */"
+ fi
+ AC_SUBST(INCLUDE_LOCALE_H)
+
+ dnl Determine which catalog format we have (if any is needed)
+ dnl For now we know about two different formats:
+ dnl Linux libc-5 and the normal X/Open format
+ test -d intl || mkdir intl
+ if test "$CATOBJEXT" = ".cat"; then
+ AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
+
+ dnl Transform the SED scripts while copying because some dumb SEDs
+ dnl cannot handle comments.
+ sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
+ fi
+ dnl po2tbl.sed is always needed.
+ sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
+ $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed
+
+ dnl In the intl/Makefile.in we have a special dependency which makes
+ dnl only sense for gettext. We comment this out for non-gettext
+ dnl packages.
+ if test "$PACKAGE" = "gettext"; then
+ GT_NO="#NO#"
+ GT_YES=
+ else
+ GT_NO=
+ GT_YES="#YES#"
+ fi
+ AC_SUBST(GT_NO)
+ AC_SUBST(GT_YES)
+
+ dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
+ dnl find the mkinstalldirs script in another subdir but ($top_srcdir).
+ dnl Try to locate is.
+ MKINSTALLDIRS=
+ if test -n "$ac_aux_dir"; then
+ MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
+ fi
+ if test -z "$MKINSTALLDIRS"; then
+ MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+ fi
+ AC_SUBST(MKINSTALLDIRS)
+
+ dnl *** For now the libtool support in intl/Makefile is not for real.
+ l=
+ AC_SUBST(l)
+
+ dnl Generate list of files to be processed by xgettext which will
+ dnl be included in po/Makefile.
+ test -d po || mkdir po
+ if test "x$srcdir" != "x."; then
+ if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
+ posrcprefix="$srcdir/"
+ else
+ posrcprefix="../$srcdir/"
+ fi
+ else
+ posrcprefix="../"
+ fi
+ rm -f po/POTFILES
+ sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
+ < $srcdir/po/POTFILES.in > po/POTFILES
+ ])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 00000000..a3f75440
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+PKG_NAME="GDM"
+
+(test -f $srcdir/configure.in \
+ && test -d $srcdir/daemon \
+ && test -f $srcdir/daemon/gdm.h) || {
+ echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+ echo " top-level gdm directory"
+ exit 1
+}
+
+. $srcdir/macros/autogen.sh
diff --git a/config/.cvsignore b/config/.cvsignore
new file mode 100644
index 00000000..35baa7a0
--- /dev/null
+++ b/config/.cvsignore
@@ -0,0 +1,7 @@
+libtool
+confdefs.h
+Makefile.in
+Gnome
+gdm.conf
+gnomerc
+Makefile \ No newline at end of file
diff --git a/config/:0 b/config/:0
new file mode 100755
index 00000000..8e91f69a
--- /dev/null
+++ b/config/:0
@@ -0,0 +1,2 @@
+#!/bin/sh
+# Stuff any local display preparation stuff here (background pics etc).
diff --git a/config/Default b/config/Default
new file mode 100644
index 00000000..63d9d335
--- /dev/null
+++ b/config/Default
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+/usr/bin/X11/xsetroot -solid "#007777"
+
+
+
diff --git a/config/Gnome.in b/config/Gnome.in
new file mode 100755
index 00000000..cf429391
--- /dev/null
+++ b/config/Gnome.in
@@ -0,0 +1,18 @@
+#!/bin/bash -login
+
+for errfile in "$HOME/.gnomerc-errors" "${TMPDIR-/tmp}/gnomerc-$USER" "/tmp/gnomerc-$USER"
+do
+ if ( cp /dev/null "$errfile" 2> /dev/null )
+ then
+ chmod 600 "$errfile"
+ exec > "$errfile" 2>&1
+ break
+ fi
+done
+
+if [ -x "$HOME/.gnomerc" ]; then
+ exec "$HOME/.gnomerc"
+else
+ exec "@sysconfdir@/gnomerc"
+fi
+
diff --git a/config/Makefile.am b/config/Makefile.am
new file mode 100644
index 00000000..f292ec9b
--- /dev/null
+++ b/config/Makefile.am
@@ -0,0 +1,75 @@
+pixmapdir = $(datadir)/pixmaps
+confdir = $(sysconfdir)/gdm
+localedir = $(sysconfdir)/gdm
+sessdir = $(sysconfdir)/gdm/Sessions
+initdir = $(sysconfdir)/gdm/Init
+authdir = $(localstatedir)/gdm
+gnomercdir = $(sysconfdir)
+
+gdm.conf: gdm.conf.in Makefile
+ sed -e 's,\@datadir\@,$(datadir),g' \
+ -e 's,\@pixmapdir\@,$(pixmapdir),g' \
+ -e 's,\@bindir\@,$(bindir),g' \
+ -e 's,\@sysconfdir\@,$(sysconfdir),g' \
+ -e 's,\@localedir\@,$(localedir),g' \
+ -e 's,\@authdir\@,$(authdir),g' \
+ < $(srcdir)/gdm.conf.in > gdm.conf.tmp; \
+ mv -f gdm.conf.tmp gdm.conf
+
+Gnome: Gnome.in Makefile
+ sed -e 's,\@sysconfdir\@,$(sysconfdir),g' \
+ < $(srcdir)/Gnome.in > Gnome.tmp \
+ && mv -f Gnome.tmp Gnome
+
+gnomerc: gnomerc.in Makefile
+ sed -e 's,\@bindir\@,$(bindir),g' \
+ < $(srcdir)/gnomerc.in > gnomerc.tmp \
+ && mv -f gnomerc.tmp gnomerc
+
+conf_SCRIPTS = gdm.conf
+locale_SCRIPTS = locale.alias
+gnomerc_SCRIPTS = gnomerc
+sess_SCRIPTS = Gnome Xsession
+init_SCRIPTS = Default
+
+EXTRA_DIST = \
+ gdm.conf.in \
+ Gnome.in \
+ gnomerc.in \
+ Xsession \
+ gdm \
+ locale.alias \
+ Default
+
+install-data-hook: gdm.conf gnomerc Gnome
+ if test '!' -d $(confdir); then \
+ $(mkinstalldirs) $(confdir); \
+ chmod 755 $(confdir); \
+ fi
+ if test '!' -d $(sessdir); then \
+ $(mkinstalldirs) $(sessdir); \
+ chmod 755 $(sessdir); \
+ fi
+ if test '!' -d $(initdir); then \
+ $(mkinstalldirs) $(initdir); \
+ chmod 755 $(initdir); \
+ fi
+ if test '!' -d $(authdir); then \
+ $(mkinstalldirs) $(authdir); \
+ chown gdm.gdm $(authdir); \
+ chmod 750 $(authdir); \
+ fi
+
+ system=`uname`; \
+ if test -f /usr/include/security/pam_appl.h; then \
+ if test '!' -d $(sysconfdir)/pam.d; then \
+ $(mkinstalldirs) $(sysconfdir)/pam.d; \
+ chmod 755 $(sysconfdir)/pam.d; \
+ fi; \
+ if test $$system = Linux && test '!' -f $(sysconfdir)/pam.d/gdm; then \
+ $(INSTALL_DATA) gdm $(sysconfdir)/pam.d/gdm; \
+ fi; \
+ if test $$system = SunOS; then \
+ echo "Please add PAM authentication for gdm in $(sysconfdir)/pam.conf!"; \
+ fi; \
+ fi
diff --git a/config/Xsession b/config/Xsession
new file mode 100755
index 00000000..11cfd153
--- /dev/null
+++ b/config/Xsession
@@ -0,0 +1,41 @@
+#!/bin/bash -login
+# $XConsortium: Xsession /main/10 1995/12/18 18:21:28 gildea $
+
+case $# in
+1)
+ case $1 in
+ failsafe)
+ exec xterm -geometry 80x24-0-0
+ ;;
+ esac
+esac
+
+# redirect errors to a file in user's home directory if we can
+for errfile in "$HOME/.xsession-errors" "${TMPDIR-/tmp}/xses-$USER" "/tmp/xses-$USER"
+do
+ if ( cp /dev/null "$errfile" 2> /dev/null )
+ then
+ chmod 600 "$errfile"
+ exec > "$errfile" 2>&1
+ break
+ fi
+done
+
+# clean up after xbanner
+freetemp
+
+startup=$HOME/.xsession
+resources=$HOME/.Xresources
+
+if [ -x "$startup" ]; then
+ exec "$startup"
+elif [ -x "$HOME/.Xclients" ]; then
+ exec "$HOME/.Xclients"
+elif [ -x /etc/X11/xinit/Xclients ]; then
+ exec /etc/X11/xinit/Xclients
+else
+ if [ -f "$resources" ]; then
+ xrdb -load "$resources"
+ fi
+ exec xsm
+fi
diff --git a/config/gdm b/config/gdm
new file mode 100644
index 00000000..71ff8d13
--- /dev/null
+++ b/config/gdm
@@ -0,0 +1,8 @@
+#%PAM-1.0
+auth required /lib/security/pam_pwdb.so shadow nullok
+auth required /lib/security/pam_nologin.so
+account required /lib/security/pam_pwdb.so
+password required /lib/security/pam_cracklib.so
+password required /lib/security/pam_pwdb.so shadow nullok use_authtok
+session required /lib/security/pam_pwdb.so
+session optional /lib/security/pam_console.so
diff --git a/config/gdm.conf.in b/config/gdm.conf.in
new file mode 100644
index 00000000..d5e4fb05
--- /dev/null
+++ b/config/gdm.conf.in
@@ -0,0 +1,60 @@
+[appearance]
+Browser=1
+Completion=1
+Logo=1
+LogoImage=@pixmapdir@/gnome-logo-large.png
+NoFaceImage=@pixmapdir@/nophoto.png
+GlobalImageDir=@datadir@/faces/
+Quiver=1
+Iconify=1
+IconFile=@pixmapdir@/gdm.xpm
+Gtkrc=
+
+[system]
+ShutdownMenu=0
+SuspendCommand=
+UserFileCutoffSize=65536
+UserIconMaxWidth=128
+UserIconMaxHeight=128
+DefaultPath=@bindir@:/usr/local/bin:/usr/bin/X11:/usr/bin:/bin
+VerboseAuth=0
+AllowRoot=0
+RelaxPermissions=0
+RetryDelay=3
+LocaleFile=@localedir@/locale.alias
+
+[messages]
+Welcome=Welcome to %h
+
+[daemon]
+SessionDir=@sysconfdir@/gdm/Sessions
+PidFile=/var/run/gdm.pid
+Greeter=@bindir@/gdmlogin --disable-sound
+Chooser=@bindir@/gdmchooser --disable-sound
+User=nobody
+Group=gdm
+DisplayInitDir=@sysconfdir@/gdm/Init
+KillInitClients=1
+PreSessionScriptDir=@sysconfdir@/gdm/PreSession
+PostSessionScriptDir=@sysconfdir@/gdm/PostSession
+AuthDir=@authdir@
+LogDir=@authdir@
+
+[servers]
+0=/usr/bin/X11/X
+#1=/usr/bin/X11/X
+
+[xdmcp]
+Enable=1
+MaxLoadAvg=10
+MaxPending=4
+MaxManageWait=20
+MaxSessions=4
+Port=177
+
+[chooser]
+ImageDir=@datadir@/hosts
+DefaultImage=@pixmapdir@/nohost.png
+
+[debug]
+Enable=0
diff --git a/config/gnomerc.in b/config/gnomerc.in
new file mode 100644
index 00000000..e45a0d17
--- /dev/null
+++ b/config/gnomerc.in
@@ -0,0 +1 @@
+@bindir@/gnome-session
diff --git a/config/locale.alias b/config/locale.alias
new file mode 100644
index 00000000..b3148a4a
--- /dev/null
+++ b/config/locale.alias
@@ -0,0 +1,54 @@
+# Locale name alias data base
+# Copyright (C) 1995 Free Software Foundation, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# The format of this file is the same as for the corresponding file of
+# the X Window System, which normally can be found in
+# /usr/lib/X11/locale/locale.alias
+# A single line contains two fields: an alias and a substitution value.
+# All entries are case independent.
+
+# Note: This file is far from being complete. If you have a value for
+# your own site which you think might be useful for others too, share it
+# with the rest of us. Send it to bug-gnu-utils@prep.ai.mit.edu.
+
+czech cs_CZ.ISO-8859-2
+danish da_DK.ISO-8859-1
+dansk da_DK.ISO-8859-1
+deutsch de_DE.ISO-8859-1
+dutch nl_NL.ISO-8859-1
+english en.ISO-8859-1
+finnish fi_FI.ISO-8859-1
+français fr_FR.ISO-8859-1
+french fr_FR.ISO-8859-1
+german de_DE.ISO-8859-1
+greek el_GR.ISO-8859-7
+hebrew iw_IL.ISO-8859-8
+hungarian hu_HU.ISO-8859-2
+icelandic is_IS.ISO-8859-1
+italian it_CH.ISO-8859-1
+japanese ja_JP.EUC
+norwegian no_NO.ISO-8859-1
+polish pl_PL.ISO-8859-2
+portuguese pt_PT.ISO-8859-1
+rumanian ro_RO.ISO-8859-2
+russian ru_SU.ISO-8859-5
+slovak sk_SK.ISO-8859-2
+slovene sl_CS.ISO-8859-2
+spanish es_ES.ISO-8859-1
+swedish sv_SE.ISO-8859-1
+turkish tr_TR.ISO-8859-9
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 00000000..f00a9025
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,108 @@
+AC_INIT(daemon/gdm.h)
+
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(gdm,2.0.0)
+AM_MAINTAINER_MODE
+AM_ACLOCAL_INCLUDE(macros)
+
+GNOME_INIT
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_STDC_HEADERS
+AC_ARG_PROGRAM
+AM_PROG_LIBTOOL
+
+GNOME_X_CHECKS
+
+AC_SUBST(CFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+
+dnl ## internationalization support
+ALL_LINGUAS="de es fr no"
+AM_GNOME_GETTEXT
+
+dnl ## Autentication scheme
+have_pam=no
+AC_CHECK_HEADERS(security/pam_appl.h, [
+ have_pam=yes
+ LIBS="$LIBS -lpam"
+ AC_DEFINE(HAVE_PAM)])
+
+if test $have_pam = no; then
+
+# Check if -lcrypt is necessary
+AC_CHECK_LIB(crypt, crypt, [
+ LIBS="$LIBS -lcrypt"])
+
+# Check for shadow passwords (hack)
+ AC_MSG_CHECKING("for /etc/shadow")
+
+ if test -e /etc/shadow; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SHADOW)
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+fi
+
+
+# TCP Wrappers for XDMCP access control
+AC_MSG_CHECKING("whether to use TCP wrappers")
+LIBWRAP_PATH=""
+for I in $LDFLAGS $LIBS -L/usr/lib; do
+ case "$I" in
+ -L*)
+ THEFILE="`echo $I | sed -e 's,^-L,,'`"
+ echo "From $I, checking in dir $THEFILE for libwrap.a" 1>&5
+ if test -f $THEFILE/libwrap.a; then
+ LIBWRAP_PATH=$THEFILE/libwrap.a
+ echo "Found $LIBWRAP_PATH" 1>&5
+ break
+ fi
+ esac
+done
+if test -n "$LIBWRAP_PATH"; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+if test -n "$LIBWRAP_PATH"; then
+ nm $LIBWRAP_PATH | grep 'T setenv' && LIBWRAP_PATH=""
+ if test -z "$LIBWRAP_PATH"; then
+ echo "*********************************************************"
+ echo " You have a broken TCP wrappers library (setenv included)"
+ echo " Please get the latest TCP wrappers package from your OS"
+ echo " vendor, or recompile TCP wrappers to not include a"
+ echo " setenv() implementation."
+ echo
+ echo "Not using TCP wrappers after all."
+ echo "*********************************************************"
+ else
+ AC_DEFINE(HAVE_TCPWRAPPERS)
+ fi
+fi
+LIBS="$LIBS $LIBWRAP_PATH"
+
+AC_PATH_PROG(ac_xauth, xauth)
+GDM_XAUTH_PATH=$ac_xauth
+
+AC_DEFINE_UNQUOTED(GDM_XAUTH_PATH, "$ac_xauth")
+
+
+AC_OUTPUT([
+Makefile
+daemon/Makefile
+gui/Makefile
+pixmaps/Makefile
+macros/Makefile
+config/Makefile
+docs/Makefile
+po/Makefile.in
+intl/Makefile
+stamp.h],[sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile])
+
+
diff --git a/daemon/.cvsignore b/daemon/.cvsignore
new file mode 100644
index 00000000..7fe75d04
--- /dev/null
+++ b/daemon/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+.deps
+gdm
+gdmgreeter
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
new file mode 100644
index 00000000..f59882b4
--- /dev/null
+++ b/daemon/Makefile.am
@@ -0,0 +1,30 @@
+## Process this file with automake to produce makefile.in
+CFLAGS += -g -Wall \
+ -Wpointer-arith \
+ -Wmissing-prototypes -Wmissing-declarations
+
+DEFS += -DGDM_CONFIG_FILE=\"@sysconfdir@/gdm/gdm.conf\"
+
+INCLUDES = -I. -I.. -I$(includedir) \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ -DLOCALEDIR=\"$(datadir)/locale\" \
+ $(GNOME_INCLUDEDIR)
+
+bin_PROGRAMS = gdm
+
+gdm_SOURCES = \
+ gdm.c \
+ gdm.h \
+ slave.c \
+ server.c \
+ verify.c \
+ misc.c \
+ auth.c \
+ cookie.c \
+ xdmcp.c \
+ filecheck.c \
+ md5.c \
+ md5.h
+
+gdm_LDADD = $(GNOME_LIBDIR) $(GNOME_LIBS) -lXdmcp -lX11 $(INTLLIBS)
+
diff --git a/daemon/auth.c b/daemon/auth.c
new file mode 100644
index 00000000..c8ccea4c
--- /dev/null
+++ b/daemon/auth.c
@@ -0,0 +1,157 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@mkp.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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * This file contains the X Authentication code
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+extern gchar *GdmAuthDir;
+extern gid_t GdmGroupId;
+
+extern gchar **gdm_arg_munch(gchar *);
+extern void gdm_cookie_generate(GdmDisplay *d);
+extern void *gdm_debug(const gchar *, ...);
+extern void *gdm_error(const gchar *, ...);
+
+void gdm_auth_secure_display(GdmDisplay *d);
+void gdm_auth_user_add(GdmDisplay *d, gchar *home);
+void gdm_auth_user_remove(GdmDisplay *d, gchar *home);
+
+
+void gdm_auth_secure_display(GdmDisplay *d)
+{
+ gchar *authstr;
+ gchar **argv;
+ pid_t authpid;
+
+ gdm_debug("gdm_auth_secure_display: Securing %s", d->name);
+
+ gdm_cookie_generate(d);
+
+ d->auth=g_strconcat(GdmAuthDir, "/", d->name, ".xauth", NULL);
+
+ if(unlink(d->auth) == -1)
+ gdm_debug(_("gdm_auth_secure_display: Could not unlink %s file: %s"),\
+ d->auth, strerror(errno));
+
+ authstr=g_strconcat(GDM_XAUTH_PATH, " -i -f ", d->auth, \
+ " add ", d->name, " . ", d->cookie, NULL);
+ argv=gdm_arg_munch(authstr);
+
+ switch(authpid=fork()) {
+
+ case 0:
+ execv(argv[0], argv);
+ gdm_error(_("gdm_auth_secure_display: Error starting xauth process: %s. Running insecure!"), strerror(errno));
+ return;
+
+ case -1:
+ gdm_error(_("gdm_auth_secure_display: Error forking xauth process. Running insecure!"));
+ return;
+
+ default:
+ waitpid(authpid, 0, 0); /* Wait for xauth to finish */
+ chown(d->auth, 0, GdmGroupId);
+ chmod(d->auth, S_IRUSR|S_IWUSR|S_IRGRP);
+ break;
+ }
+
+}
+
+
+void gdm_auth_user_add(GdmDisplay *d, gchar *home)
+{
+ gchar *authfile, *authstr;
+ gchar **argv;
+ pid_t authpid;
+
+ gdm_debug("gdm_auth_user_add: Adding cookie to %s", home);
+
+ authfile=g_strconcat(home, "/.Xauthority", NULL);
+ authstr=g_strconcat(GDM_XAUTH_PATH, " -i -f ", authfile, \
+ " add ", d->name, " . ", d->cookie, NULL);
+
+ argv=gdm_arg_munch(authstr);
+ g_free(authstr);
+
+ switch(authpid=fork()) {
+
+ case 0:
+ execv(argv[0], argv);
+ gdm_error(_("gdm_auth_user_add: Error starting xauth process: %s"), strerror(errno));
+ return;
+
+ case -1:
+ gdm_error(_("gdm_auth_user_add: Error forking xauth process."));
+ return;
+
+ default:
+ waitpid(authpid, 0,0); /* Wait for xauth to finish */
+ chmod(authfile, S_IRUSR|S_IWUSR);
+ g_free(authfile);
+ break;
+
+ }
+}
+
+
+void gdm_auth_user_remove(GdmDisplay *d, gchar *home)
+{
+ gchar *authstr;
+ gchar **argv;
+ pid_t authpid;
+
+ gdm_debug("gdm_auth_user_remove: Removing cookie from %s", home);
+
+ authstr=g_strconcat(GDM_XAUTH_PATH, " -i -f ", home, "/.Xauthority", \
+ " remove ", d->name, NULL);
+ argv=gdm_arg_munch(authstr);
+ g_free(authstr);
+
+ switch(authpid=fork()) {
+
+ case 0:
+ execv(argv[0], argv);
+ gdm_error(_("gdm_auth_user_remove: Error starting xauth process: %s"), strerror(errno));
+ return;
+
+ case -1:
+ gdm_error(_("gdm_auth_user_remove: Error forking xauth process."));
+ return;
+
+ default:
+ waitpid(authpid, 0, 0); /* Wait for xauth to finish */
+ break;
+
+ }
+}
+
+/* EOF */
diff --git a/daemon/cookie.c b/daemon/cookie.c
new file mode 100644
index 00000000..301f479c
--- /dev/null
+++ b/daemon/cookie.c
@@ -0,0 +1,106 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@mkp.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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Functions for generating MIT-MAGIC-COOKIEs.
+ *
+ * This code was derived (stolen!) from mcookie.c written by Rik Faith
+ * <faith@cs.unc.edu>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <gnome.h>
+
+#include "gdm.h"
+#include "md5.h"
+
+#define MAXBUFFERSIZE 512
+
+struct rngs {
+ const char *path;
+ int length;
+} rngs[] = {
+ { "/dev/random", 16 },
+ { "/dev/urandom", 128 },
+ { "/proc/stat", MAXBUFFERSIZE },
+ { "/proc/loadavg", MAXBUFFERSIZE },
+ { "/dev/audio", MAXBUFFERSIZE },
+};
+
+#define RNGS (sizeof(rngs)/sizeof(struct rngs))
+
+void gdm_cookie_generate(GdmDisplay *);
+
+void
+gdm_cookie_generate(GdmDisplay *d)
+{
+ int i;
+ struct MD5Context ctx;
+ unsigned char digest[16];
+ unsigned char buf[MAXBUFFERSIZE];
+ int fd;
+ pid_t pid;
+ int r;
+ struct timeval tv;
+ struct timezone tz;
+ char sub[8];
+ char cookie[40];
+
+ sub[0]='\0';
+ cookie[0]='\0';
+
+ MD5Init( &ctx );
+ gettimeofday( &tv, &tz );
+ MD5Update( &ctx, (unsigned char *)&tv, sizeof( tv ) );
+ pid = getppid();
+ MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
+ pid = getpid();
+ MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
+
+ for (i = 0; i < RNGS; i++) {
+ if ((fd = open( rngs[i].path, O_RDONLY|O_NONBLOCK )) >= 0) {
+ r = read( fd, buf, sizeof( buf ) );
+ if (r > 0)
+ MD5Update( &ctx, buf, r );
+ else
+ r = 0;
+ close( fd );
+ if (r >= rngs[i].length) break;
+ }
+ }
+
+ MD5Final(digest, &ctx);
+
+ for (i = 0; i < 16; i++) {
+ sprintf(sub, "%02x", digest[i]);
+ strcat(cookie, sub);
+ }
+
+ d->cookie=g_strdup(cookie);
+ d->bcookie=g_strndup(digest, 16);
+}
+
+
+/* EOF */
diff --git a/daemon/filecheck.c b/daemon/filecheck.c
new file mode 100644
index 00000000..a2623dd6
--- /dev/null
+++ b/daemon/filecheck.c
@@ -0,0 +1,120 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+gboolean gdm_file_check(gchar *caller, uid_t user, gchar *dir, gchar *file, gboolean absentok);
+
+extern gint GdmUserMaxFile;
+extern gint GdmRelaxPerms;
+
+gboolean
+gdm_file_check(gchar *caller, uid_t user, gchar *dir, gchar *file, gboolean absentok)
+{
+ struct stat statbuf;
+ gchar *str;
+
+ /* Stat directory */
+ if(stat(dir, &statbuf) == -1)
+ return(FALSE);
+
+ /* Check if dir is owned by the user */
+ if(statbuf.st_uid != user) {
+ syslog(LOG_WARNING, _("%s: %s is not owned by uid %d."), caller, dir, user);
+ return(FALSE);
+ }
+
+ /* Check if group has write permission */
+ if(GdmRelaxPerms<1 && (statbuf.st_mode & S_IWGRP) == S_IWGRP) {
+ syslog(LOG_WARNING, _("%s: %s is writable by group."), caller, dir);
+ return(FALSE);
+ }
+
+ /* Check if other has write permission */
+ if(GdmRelaxPerms<2 && (statbuf.st_mode & S_IWOTH) == S_IWOTH) {
+ syslog(LOG_WARNING, _("%s: %s is writable by other."), caller, dir);
+ return(FALSE);
+ }
+
+ str=g_strconcat(dir, "/", file, NULL);
+
+ /* Stat file */
+ if(stat(str, &statbuf) == -1) {
+ g_free(str);
+
+ /* Return true if file is absent and that is ok */
+ if(absentok)
+ return(TRUE);
+ else
+ return(FALSE);
+ }
+
+ /* Check that it is a regular file ... */
+ if(! S_ISREG(statbuf.st_mode)) {
+ syslog(LOG_WARNING,_("%s: %s is not a regular file."), caller, str);
+ g_free(str);
+ return(FALSE);
+ }
+
+ /* ... owned by the user ... */
+ if(statbuf.st_uid != user) {
+ syslog(LOG_WARNING, _("%s: %s is not owned by uid %d."), caller, str, user);
+ g_free(str);
+ return(FALSE);
+ }
+
+ /* ... unwritable by group ... */
+ if(GdmRelaxPerms<1 && (statbuf.st_mode & S_IWGRP) == S_IWGRP) {
+ syslog(LOG_WARNING, _("%s: %s is writable by group."), caller, str);
+ g_free(str);
+ return(FALSE);
+ }
+
+ /* ... unwritable by others ... */
+ if(GdmRelaxPerms<2 && (statbuf.st_mode & S_IWOTH) == S_IWOTH) {
+ syslog(LOG_WARNING, _("%s: %s is writable by group/other."), caller, str);
+ g_free(str);
+ return(FALSE);
+ }
+
+ /* ... and smaller than sysadmin specified limit. */
+ if(statbuf.st_size > GdmUserMaxFile) {
+ syslog(LOG_WARNING, _("%s: %s is bigger than sysadmin specified maximum file size."), caller, str);
+ g_free(str);
+ return(FALSE);
+ }
+
+ g_free(str);
+
+ /* Yeap, this file is ok */
+ return(TRUE);
+}
+
+/* EOF */
diff --git a/daemon/gdm.c b/daemon/gdm.c
new file mode 100644
index 00000000..7481d292
--- /dev/null
+++ b/daemon/gdm.c
@@ -0,0 +1,626 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <strings.h>
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <ctype.h>
+#include <config.h>
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+extern void gdm_slave_start(GdmDisplay *);
+extern gchar **gdm_arg_munch(const gchar *p);
+extern void gdm_fail(const gchar *, ...);
+extern void gdm_info(const gchar *, ...);
+extern void gdm_error(const gchar *, ...);
+extern GdmDisplay *gdm_server_alloc(gint id, gchar *command);
+extern void gdm_server_start(GdmDisplay *d);
+extern void gdm_server_stop(GdmDisplay *d);
+extern void gdm_server_restart(GdmDisplay *d);
+extern void gdm_debug(const gchar *format, ...);
+extern int gdm_xdmcp_init(void);
+extern void gdm_xdmcp_run(void);
+extern void gdm_xdmcp_close(void);
+
+gint gdm_display_manage(GdmDisplay *d);
+void gdm_display_dispose (GdmDisplay *d);
+static void gdm_local_servers_start(GdmDisplay *d);
+static void gdm_display_unmanage(GdmDisplay *d);
+
+GSList *displays;
+gint sessions=0;
+static gchar *GdmUser;
+static gchar *GdmGroup;
+
+uid_t GdmUserId;
+gid_t GdmGroupId;
+gchar *GdmSessDir = NULL;
+gchar *GdmGreeter = NULL;
+gchar *GdmLogDir = NULL;
+gchar *GdmDisplayInit = NULL;
+gchar *GdmPreSession = NULL;
+gchar *GdmPostSession = NULL;
+gchar *GdmHalt = NULL;
+gchar *GdmReboot = NULL;
+gchar *GdmAuthDir = NULL;
+gchar *GdmUserAuthFile = NULL;
+gchar *GdmSuspend = NULL;
+gchar *GdmPidFile = NULL;
+gchar *GdmDefaultPath = NULL;
+gint GdmKillInitClients = 0;
+gint GdmUserMaxFile = 0;
+gint GdmXdmcp;
+gint GdmMaxPending;
+gint GdmMaxManageWait;
+gint GdmMaxSessions;
+gint GdmPort;
+gint GdmDebug;
+gint GdmVerboseAuth;
+gint GdmAllowRoot;
+gint GdmRelaxPerms;
+gint GdmRetryDelay;
+
+typedef struct _childstat ChildStat;
+struct _childstat { pid_t pid; gint status; };
+
+
+void
+gdm_display_dispose (GdmDisplay *d)
+{
+ if(d->type == DISPLAY_XDMCP) {
+ displays=g_slist_remove(displays, d);
+ sessions--;
+ }
+
+ if(d->name) {
+ gdm_debug("gdm_display_dispose: Disposing %s", d->name);
+ g_free(d->name);
+ }
+
+ if(d->auth)
+ g_free(d->auth);
+
+ if(d->command)
+ g_free(d->command);
+
+ if(d->cookie)
+ g_free(d->cookie);
+
+ if(d->bcookie)
+ g_free(d->bcookie);
+
+ g_free(d);
+}
+
+
+static void
+gdm_config_parse (void)
+{
+ gchar *k, *v;
+ void *iter;
+ struct passwd *pwent;
+ struct group *grent;
+ struct stat statbuf;
+
+ displays = NULL;
+
+ if(stat(GDM_CONFIG_FILE, &statbuf) == -1)
+ gdm_fail(_("gdm_config_parse: No configuration file: %s. Aborting."), GDM_CONFIG_FILE);
+
+ gnome_config_push_prefix ("=" GDM_CONFIG_FILE "=/");
+ GdmPidFile=g_strdup(gnome_config_get_string("daemon/pidfile=/var/run/gdm.pid"));
+ GdmUser=g_strdup(gnome_config_get_string("daemon/user=gdm"));
+ GdmGroup=g_strdup(gnome_config_get_string("daemon/group=gdm"));
+ GdmGreeter=g_strdup(gnome_config_get_string("daemon/greeter"));
+ GdmSessDir=g_strdup(gnome_config_get_string("daemon/sessiondir"));
+ GdmLogDir=g_strdup(gnome_config_get_string("daemon/logdir"));
+ GdmDisplayInit=g_strdup(gnome_config_get_string("daemon/displayinitdir"));
+ GdmPreSession=g_strdup(gnome_config_get_string("daemon/presessionscriptdir"));
+ GdmPostSession=g_strdup(gnome_config_get_string("daemon/postsessionscriptdir"));
+ GdmHalt=g_strdup(gnome_config_get_string("daemon/haltcommand=/sbin/shutdown -h now"));
+ GdmReboot=g_strdup(gnome_config_get_string("daemon/rebootcommand=/sbin/shutdown -r now"));
+ GdmSuspend=g_strdup(gnome_config_get_string("daemon/suspendcommand"));
+ GdmAuthDir=g_strdup(gnome_config_get_string("daemon/authdir"));
+ GdmUserAuthFile=g_strdup(gnome_config_get_string("daemon/userauthfile=.Xauthority"));
+ GdmKillInitClients=gnome_config_get_int("daemon/killinitclients=1");
+ GdmVerboseAuth=gnome_config_get_int("system/verboseauth=1");
+ GdmAllowRoot=gnome_config_get_int("system/allowroot=0");
+ GdmRelaxPerms=gnome_config_get_int("system/relaxpermissions=0");
+ GdmRetryDelay=gnome_config_get_int("system/retrydelay=3");
+ GdmUserMaxFile=gnome_config_get_int("system/userfilecutoffsize=65536");
+ GdmXdmcp=gnome_config_get_int("xdmcp/enable=1");
+ GdmMaxPending=gnome_config_get_int("xdmcp/maxpending=4");
+ GdmMaxManageWait=gnome_config_get_int("xdmcp/maxmanagewait=20");
+ GdmMaxSessions=gnome_config_get_int("xdmcp/maxsessions=4");
+ GdmPort=gnome_config_get_int("xdmcp/port=177");
+ GdmDebug=gnome_config_get_int("debug/enable=0");
+ GdmDefaultPath=g_strdup(gnome_config_get_string("system/defaultpath=/bin:/usr/bin:/usr/X11/bin:/usr/local/bin"));
+
+ if(GdmGreeter==NULL && stat("/usr/local/bin/gdmgreeter", &statbuf)==0)
+ GdmGreeter="/usr/local/bin/gdmgreeter";
+
+ if(GdmGreeter==NULL && stat("/usr/bin/gdmgreeter", &statbuf)==0)
+ GdmGreeter="/usr/bin/gdmgreeter";
+
+ if(GdmGreeter==NULL && stat("/opt/gnome/bin/gdmgreeter", &statbuf)==0)
+ GdmGreeter="/opt/gnome/bin/gdmgreeter";
+
+ if(GdmGreeter==NULL)
+ gdm_fail(_("gdm_config_parse: No greeter specified and default not found."));
+
+ if(GdmAuthDir==NULL && stat("/var/gdm", &statbuf)==0)
+ GdmAuthDir="/var/gdm";
+
+ if(GdmAuthDir==NULL && stat("/var/lib/gdm", &statbuf)==0)
+ GdmAuthDir="/var/lib/gdm";
+
+ if(GdmAuthDir==NULL && stat("/opt/gnome/var/gdm", &statbuf)==0)
+ GdmAuthDir="/opt/gnome/var/gdm";
+
+ if(GdmAuthDir==NULL)
+ gdm_fail(_("gdm_config_parse: No authdir specified and default not found."));
+
+ if(GdmLogDir==NULL)
+ GdmLogDir=GdmAuthDir;
+
+ if(GdmSessDir==NULL && stat("/usr/local/etc/gdm/Sessions", &statbuf)==0)
+ GdmSessDir="/usr/local/etc/gdm/Sessions";
+
+ if(GdmSessDir==NULL && stat("/usr/etc/gdm/Sessions", &statbuf)==0)
+ GdmSessDir="/usr/etc/gdm/Sessions";
+
+ if(GdmSessDir==NULL && stat("/etc/gdm/Sessions", &statbuf)==0)
+ GdmSessDir="/etc/gdm/Sessions";
+
+ if(GdmSessDir==NULL && stat("/etc/X11/gdm/Sessions", &statbuf)==0)
+ GdmSessDir="/etc/X11/gdm/Sessions";
+
+ if(GdmSessDir==NULL)
+ gdm_fail(_("gdm_config_parse: No sessions directory specified and default not found."));
+
+ gnome_config_pop_prefix();
+
+ iter=gnome_config_init_iterator("=" GDM_CONFIG_FILE "=/servers");
+ iter=gnome_config_iterator_next (iter, &k, &v);
+
+ while (iter) {
+
+ if(isdigit(*k))
+ displays=g_slist_append(displays, gdm_server_alloc(atoi(k), v));
+ else
+ gdm_info(_("gdm_config_parse: Invalid server line in config file. Ignoring!"));
+
+ iter=gnome_config_iterator_next (iter, &k, &v);
+ }
+
+ if(!displays && !GdmXdmcp)
+ gdm_fail(_("gdm_config_parse: Xdmcp disabled and no local servers defined. Aborting!"));
+
+ pwent = getpwnam(GdmUser);
+
+ if(!pwent)
+ gdm_fail(_("gdm_config_parse: Can't find the gdm user (%s). Aborting!"), GdmUser);
+ else
+ GdmUserId=pwent->pw_uid;
+
+ if(GdmUserId==0)
+ gdm_fail(_("gdm_config_parse: The gdm user should not be root. Aborting!"));
+
+ grent = getgrnam(GdmGroup);
+
+ if(!grent)
+ gdm_fail(_("gdm_config_parse: Can't find the gdm group (%s). Aborting!"), GdmGroup);
+ else
+ GdmGroupId=grent->gr_gid;
+
+
+ if(GdmGroupId==0)
+ gdm_fail(_("gdm_config_parse: The gdm group should not be root. Aborting!"));
+
+ setegid(GdmGroupId); /* gid remains `gdm' */
+ seteuid(GdmUserId);
+
+ /* Enter paranoia mode */
+ if(stat(GdmAuthDir, &statbuf) == -1)
+ gdm_fail(_("gdm_config_parse: Authdir %s does not exist. Aborting."), GdmAuthDir);
+
+ if(! S_ISDIR(statbuf.st_mode))
+ gdm_fail(_("gdm_config_parse: Authdir %s is not a directory. Aborting."), GdmAuthDir);
+
+ if(statbuf.st_uid != GdmUserId || statbuf.st_gid != GdmGroupId)
+ gdm_fail(_("gdm_config_parse: Authdir %s is not owned by user %s, group %s. Aborting."), GdmAuthDir, GdmUser, GdmGroup);
+
+ if(statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRGRP|S_IXGRP))
+ gdm_fail(_("gdm_config_parse: Authdir %s has wrong permissions. Should be 750. Aborting."), GdmAuthDir, statbuf.st_mode);
+
+ seteuid(0);
+}
+
+
+static void
+gdm_local_servers_start(GdmDisplay *d)
+{
+ if(d && d->type == DISPLAY_LOCAL) {
+ gdm_debug("gdm_local_servers_start: Starting %s", d->name);
+ gdm_server_start(d);
+ }
+}
+
+
+gint
+gdm_display_manage(GdmDisplay *d)
+{
+ sigset_t mask, omask;
+
+ if(!d)
+ return(FALSE);
+
+ gdm_debug("gdm_display_manage: Managing %s", d->name);
+
+ /* If we have an old slave process hanging around, kill it */
+ if(d->slavepid) {
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, &omask);
+
+ kill(d->slavepid, SIGINT);
+ waitpid(d->slavepid, 0, 0);
+
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+ }
+
+ switch(d->slavepid=fork()) {
+
+ case 0:
+
+ setpgid(0, 0);
+
+ /* Close XDMCP fd in slave process */
+ gdm_xdmcp_close();
+
+ if(d->type == DISPLAY_LOCAL && d->servstat == SERVER_RUNNING)
+ gdm_slave_start(d);
+
+ if(d->type == DISPLAY_XDMCP && d->dispstat == XDMCP_MANAGED)
+ gdm_slave_start(d);
+
+ break;
+
+ case -1:
+ gdm_error(_("gdm_display_manage: Failed forking gdm slave process for %d"), d->name);
+ return(FALSE);
+
+ default:
+ gdm_debug("gdm_display_manage: Forked slave: %d", d->slavepid);
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+static void
+gdm_child_handler(gint sig)
+{
+ pid_t pid;
+ gint exitstatus, status=0;
+ GSList *list=displays;
+ GdmDisplay *d;
+ gchar **argv;
+
+ /* Get status from all dead children */
+ while((pid=waitpid(-1, &exitstatus, WNOHANG)) > 0) {
+
+ if(WIFEXITED(exitstatus))
+ status=WEXITSTATUS(exitstatus);
+
+ gdm_debug("gdm_child_handler: child %d returned %d", pid, status);
+
+ if(pid < 1)
+ return;
+
+ while(list && list->data) {
+
+ d=list->data;
+ gdm_debug("gdm_child_handler: %s", d->name);
+
+ /* X server died */
+ if(pid == d->servpid) {
+ d->servpid=0;
+
+ switch(status) {
+
+ case SERVER_SUCCESS:
+ case SERVER_FAILURE:
+ gdm_server_start(d);
+ break;
+
+ case SERVER_NOTFOUND:
+ case SERVER_ABORT:
+ gdm_display_unmanage(d);
+ break;
+
+ default:
+ gdm_debug("gdm_child_handler: Server process returned unknown status %d", status);
+ gdm_display_unmanage(d);
+ break;
+ }
+ }
+
+ /* Slave died */
+ if(pid==d->slavepid) {
+ d->slavepid=0;
+
+ switch(status) {
+
+ case DISPLAY_REMANAGE:
+
+ if(d->type == DISPLAY_LOCAL && d->dispstat != DISPLAY_ABORT) {
+ d->dispstat=DISPLAY_DEAD;
+ gdm_server_restart(d);
+ }
+
+ if(d->type == DISPLAY_XDMCP)
+ gdm_display_unmanage(d);
+
+ break;
+
+ case DISPLAY_ABORT:
+ gdm_info(_("gdm_child_action: Aborting display %s"), d->name);
+ gdm_display_unmanage(d);
+ break;
+
+ case DISPLAY_REBOOT:
+ gdm_info(_("gdm_child_action: Master rebooting..."));
+ g_slist_foreach(displays, (GFunc) gdm_display_unmanage, NULL);
+ closelog();
+ unlink(GdmPidFile);
+ argv=gdm_arg_munch(GdmReboot);
+ execv(argv[0], argv);
+ gdm_error(_("gdm_child_action: Reboot failed: %s"), strerror(errno));
+ break;
+
+ case DISPLAY_HALT:
+ gdm_info(_("gdm_child_action: Master halting..."));
+ g_slist_foreach(displays, (GFunc) gdm_display_unmanage, NULL);
+ closelog();
+ unlink(GdmPidFile);
+ argv=gdm_arg_munch(GdmHalt);
+ execv(argv[0], argv);
+ gdm_error(_("gdm_child_action: Halt failed: %s"), strerror(errno));
+ break;
+
+ case DISPLAY_RESERVER:
+ default:
+ gdm_debug("gdm_child_action: Slave process returned %d", status);
+
+ if(d->type == DISPLAY_LOCAL && d->dispstat != DISPLAY_ABORT) {
+ d->dispstat=DISPLAY_DEAD;
+ gdm_server_start(d);
+ }
+
+ if(d->type == DISPLAY_XDMCP)
+ gdm_display_unmanage(d);
+
+ break;
+ }
+ }
+
+ list=list->next;
+ }
+ }
+}
+
+
+static void
+gdm_display_unmanage(GdmDisplay *d)
+{
+ if(!d)
+ return;
+
+ gdm_debug("gdm_display_unmanage: Stopping %s", d->name);
+
+ if(d->type == DISPLAY_LOCAL) {
+
+ /* Kill slave and all its children */
+ if(d->slavepid) {
+ kill(-(d->slavepid), SIGTERM);
+ waitpid(d->slavepid, 0, 0);
+ d->slavepid=0;
+ }
+
+ if(d->servpid) {
+ gdm_server_stop(d);
+ }
+
+ d->dispstat=DISPLAY_DEAD;
+ }
+ else { /* DISPLAY_XDMCP */
+ if(d->slavepid) {
+ kill(d->slavepid, SIGTERM);
+ waitpid(d->slavepid, 0, 0);
+ d->slavepid=0;
+ }
+
+ gdm_display_dispose(d);
+ }
+}
+
+
+static void
+gdm_term_handler(int sig)
+{
+ sigset_t mask;
+
+ gdm_debug("gdm_term_handler: Got TERM/INT. Going down!");
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
+
+ g_slist_foreach(displays, (GFunc) gdm_display_unmanage, NULL);
+
+ closelog();
+ unlink(GdmPidFile);
+ exit(EXIT_SUCCESS);
+}
+
+
+static void
+gdm_daemonify(void)
+{
+ FILE *pf;
+ pid_t pid;
+
+ if((pid=fork())) {
+ if((pf=fopen(GdmPidFile, "w"))) {
+ fprintf(pf, "%d\n", pid);
+ fclose(pf);
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ if(pid<0)
+ gdm_fail(_("gdm_daemonify: fork() failed!"));
+
+ if(setsid() < 0)
+ gdm_fail(_("gdm_daemonify: setsid() failed: %s!"), strerror(errno));
+
+ chdir(GdmAuthDir);
+ umask(022);
+
+ close(0);
+ close(1);
+ close(2);
+
+ open ("/dev/null", O_RDONLY);
+ dup2 (0, 1);
+ dup2 (0, 2);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ sigset_t mask;
+ struct sigaction term, child;
+ FILE *pf;
+ GMainLoop *main_loop;
+
+ /* xdm compatible error message */
+ if(getuid()) {
+ fprintf(stderr, _("Only root wants to run gdm\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ umask (022);
+ gnomelib_init("gdm", VERSION);
+ main_loop = g_main_new(FALSE);
+ openlog("gdm", LOG_PID, LOG_DAEMON);
+
+ gdm_config_parse();
+
+ if(!access(GdmPidFile, R_OK)) {
+ /* Check the process is still alive. Don't abort otherwise. */
+ int pidv;
+
+ pf=fopen(GdmPidFile, "r");
+ if(pf && fscanf(pf, "%d", &pidv)==1 && kill(pidv,0)!=-1) {
+ fclose(pf);
+ fprintf(stderr, _("gdm already running. Aborting!\n\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ fclose(pf);
+ fprintf(stderr, _("According to %s, gdm was already running (%d),\n"
+ "but seems to have been murdered mysteriously.\n"), GdmPidFile, pidv);
+ unlink(GdmPidFile);
+ }
+
+ /* Become daemon unless started in -nodaemon mode or child of init */
+ if( (argc==2 && strcmp(argv[1],"-nodaemon")==0) || getppid()==1) {
+ if((pf=fopen(GdmPidFile, "w"))) {
+ fprintf(pf, "%d\n", getpid());
+ fclose(pf);
+ }
+ }
+ else
+ gdm_daemonify();
+
+ /* Signal handling */
+ term.sa_handler = gdm_term_handler;
+ term.sa_flags = SA_RESTART;
+ sigemptyset(&term.sa_mask);
+
+ if(sigaction(SIGTERM, &term, NULL) < 0)
+ gdm_fail(_("gdm_main: Error setting up TERM signal handler"));
+
+ if(sigaction(SIGINT, &term, NULL) < 0)
+ gdm_fail(_("gdm_main: Error setting up INT signal handler"));
+
+ child.sa_handler = gdm_child_handler;
+ child.sa_flags = SA_RESTART|SA_NOCLDSTOP;
+ sigemptyset(&child.sa_mask);
+ sigaddset(&child.sa_mask, SIGCHLD);
+
+ if(sigaction(SIGCHLD, &child, NULL) < 0)
+ gdm_fail(_("gdm_main: Error setting up CHLD signal handler"));
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
+ gdm_debug("gdm_main: Here we go...");
+
+ /* Init XDMCP if applicable */
+ if(GdmXdmcp)
+ gdm_xdmcp_init();
+
+ /* Start local X servers */
+ g_slist_foreach(displays, (GFunc) gdm_local_servers_start, NULL);
+
+ /* Accept remote connections */
+ if(GdmXdmcp) {
+ gdm_debug("Accepting XDMCP connections...");
+ gdm_xdmcp_run();
+ }
+
+ g_main_run(main_loop);
+
+ for(;;)
+ pause();
+
+ return (EXIT_SUCCESS);
+}
+
+/* EOF */
diff --git a/daemon/gdm.h b/daemon/gdm.h
new file mode 100644
index 00000000..463231fe
--- /dev/null
+++ b/daemon/gdm.h
@@ -0,0 +1,86 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998 Martin Kasper Petersen <mkp@mkp.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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __GDM_H__
+#define __GDM_H__
+
+#define DISPLAY_LOCAL 1 /* Local X server */
+#define DISPLAY_XDMCP 2 /* Remote display */
+
+#define SERVER_SUCCESS 0 /* X server default */
+#define SERVER_FAILURE 1 /* X server default */
+#define SERVER_NOTFOUND 127 /* X server default */
+#define SERVER_DEAD 250 /* Server stopped */
+#define SERVER_STARTED 251 /* Server started but not ready for connections yet */
+#define SERVER_RUNNING 252 /* Server running and ready for connections */
+#define SERVER_ABORT 253 /* Server failed badly. Suspending display. */
+
+#define DISPLAY_SUCCESS 0 /* All systems are go */
+#define DISPLAY_REMANAGE 2 /* Restart display */
+#define DISPLAY_ABORT 4 /* Houston, we have a problem */
+#define DISPLAY_REBOOT 8 /* Rebewt */
+#define DISPLAY_HALT 16 /* Halt */
+#define DISPLAY_DEAD 32 /* Display not configured/started yet */
+#define DISPLAY_RESERVER 64 /* XIO Error */
+
+#define XDMCP_DEAD 0
+#define XDMCP_PENDING 1
+#define XDMCP_MANAGED 2
+
+#define GDM_MSGERR 'M'
+#define GDM_NOECHO 'K'
+#define GDM_PROMPT 'P'
+#define GDM_SESS '.'
+#define GDM_LANG 'N'
+#define GDM_SSESS 'E'
+#define GDM_SLANG 'T'
+#define GDM_RESET '!'
+#define GDM_QUIT 'Q'
+
+
+#define FIELD_SIZE 64
+#define PIPE_SIZE 1024
+
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+
+typedef struct _GdmDisplay GdmDisplay;
+
+struct _GdmDisplay {
+ CARD32 sessionid;
+ Display *dsp;
+ gchar *auth;
+ gchar *command;
+ gchar *cookie;
+ gchar *bcookie;
+ gchar *name;
+ gint dispstat;
+ gint id;
+ gint servstat;
+ gint type;
+ gint dispnum;
+ pid_t greetpid;
+ pid_t servpid;
+ pid_t sesspid;
+ pid_t slavepid;
+ time_t acctime;
+};
+
+#endif /* __GDM_H__ */
+
+/* EOF */
diff --git a/daemon/md5.c b/daemon/md5.c
new file mode 100644
index 00000000..005568b5
--- /dev/null
+++ b/daemon/md5.c
@@ -0,0 +1,253 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+#include <string.h> /* for memcpy() */
+#include "md5.h"
+
+#ifndef HIGHFIRST
+#define byteReverse(buf, len) /* Nothing */
+#else
+void byteReverse(unsigned char *buf, unsigned longs);
+
+#ifndef ASM_MD5
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+void byteReverse(unsigned char *buf, unsigned longs)
+{
+ uint32 t;
+ do {
+ t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(uint32 *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+#endif
+#endif
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+ uint32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32 *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32 *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32 *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((uint32 *) ctx->in)[14] = ctx->bits[0];
+ ((uint32 *) ctx->in)[15] = ctx->bits[1];
+
+ MD5Transform(ctx->buf, (uint32 *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void MD5Transform(uint32 buf[4], uint32 const in[16])
+{
+ register uint32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+#endif
+
diff --git a/daemon/md5.h b/daemon/md5.h
new file mode 100644
index 00000000..e264f686
--- /dev/null
+++ b/daemon/md5.h
@@ -0,0 +1,27 @@
+#ifndef MD5_H
+#define MD5_H
+
+#ifdef __alpha
+typedef unsigned int uint32;
+#else
+typedef unsigned long uint32;
+#endif
+
+struct MD5Context {
+ uint32 buf[4];
+ uint32 bits[2];
+ unsigned char in[64];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+ unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+void MD5Transform(uint32 buf[4], uint32 const in[16]);
+
+/*
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
+ */
+typedef struct MD5Context MD5_CTX;
+
+#endif /* !MD5_H */
diff --git a/daemon/misc.c b/daemon/misc.c
new file mode 100644
index 00000000..eb1408f0
--- /dev/null
+++ b/daemon/misc.c
@@ -0,0 +1,289 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <syslog.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+
+gchar **gdm_arg_munch(gchar *p);
+gint gdm_exec_script(GdmDisplay *d, gchar *dir);
+void gdm_exec_command(gchar *cmd);
+void gdm_fail(const gchar *format, ...);
+void gdm_abort(const gchar *format, ...);
+void gdm_info(const gchar *format, ...);
+void gdm_error(const gchar *format, ...);
+void gdm_debug(const gchar *format, ...);
+void gdm_remanage(const gchar *format, ...);
+void gdm_putenv(gchar *s);
+
+extern gchar *GdmPidFile;
+extern gchar *GdmDefaultPath;
+extern gint GdmDebug;
+
+
+gchar **
+gdm_arg_munch(gchar *p)
+{
+ gchar *x=strdup(p);
+ gint quoted=0;
+ gint argn=0;
+ static gchar *argv[16];
+
+ while(*x)
+ {
+ while(*x && isspace(*x))
+ x++;
+
+ if(*x=='"')
+ {
+ quoted=1;
+ x++;
+ }
+
+ argv[argn]=x;
+
+ while(*x)
+ {
+ if(*x=='"' && quoted)
+ break;
+ if(*x==' ' && !quoted)
+ break;
+ x++;
+ }
+
+ if(*x)
+ *x++=0;
+ argn++;
+ if(argn==16)
+ break;
+ }
+
+ while(argn<=16) {
+ argv[argn]=NULL;
+ argn++;
+ };
+
+ return argv;
+}
+
+
+/* Execute a script and wait for it to finish */
+gint
+gdm_exec_script(GdmDisplay *d, gchar *dir)
+{
+ pid_t pid;
+ gchar *script, *defscript, *scr;
+ gchar **argv;
+ gint status;
+
+ script = g_strconcat(dir, "/", d->name, NULL);
+ defscript = g_strconcat(dir, "/Default", NULL);
+
+ if(!access(script, R_OK|X_OK))
+ scr=script;
+ else if (!access(defscript, R_OK|X_OK))
+ scr=defscript;
+ else
+ return(EXIT_SUCCESS);
+
+ switch(pid=fork()) {
+
+ case 0:
+ gdm_putenv(g_strconcat("PATH=", GdmDefaultPath, NULL));
+ argv=gdm_arg_munch(scr);
+ execv(argv[0], argv);
+ syslog(LOG_ERR, _("gdm_exec_script: Failed starting: %s"), scr);
+ return(EXIT_SUCCESS);
+
+ case -1:
+ syslog(LOG_ERR, _("gdm_exec_script: Can't fork script process!"));
+ return(EXIT_SUCCESS);
+
+ default:
+ waitpid(pid, &status, 0); /* Wait for script to finish */
+
+ if(WIFEXITED(status))
+ return(WEXITSTATUS(status));
+ else
+ return(EXIT_SUCCESS);
+ };
+}
+
+
+void
+gdm_exec_command(gchar *cmd)
+{
+ pid_t pid;
+ gchar **argv;
+
+ if(!cmd) return;
+
+ switch(pid=fork()) {
+
+ case 0:
+ gdm_putenv(g_strconcat("PATH=", GdmDefaultPath, NULL));
+ argv=gdm_arg_munch(cmd);
+ execvp(argv[0], argv);
+ syslog(LOG_ERR, _("gdm_exec_command: Failed starting: %s"), cmd);
+ exit(EXIT_FAILURE);
+
+ case -1:
+ syslog(LOG_ERR, _("gdm_exec_command: Can't fork process!"));
+ break;
+
+ default:
+ break;
+ };
+}
+
+
+/* Log error and abort master daemon */
+void
+gdm_fail(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_ERR, s);
+ fprintf(stderr, s);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+
+ g_free(s);
+ unlink(GdmPidFile);
+ closelog();
+
+ exit(EXIT_FAILURE);
+}
+
+
+/* Log error and abort the slave daemon */
+void
+gdm_abort(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_ERR, s);
+
+ g_free(s);
+
+ exit(DISPLAY_ABORT);
+}
+
+
+/* Remanage display */
+void
+gdm_remanage(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_ERR, s);
+
+ g_free(s);
+
+ exit(DISPLAY_REMANAGE);
+}
+
+
+/* Log non fatal error/message */
+void
+gdm_info(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_INFO, s);
+
+ g_free(s);
+}
+
+
+/* Log error condition */
+void
+gdm_error(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_ERR, s);
+
+ g_free(s);
+}
+
+
+/* Log debug messages */
+void
+gdm_debug(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ if(GdmDebug) {
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_DEBUG, s);
+
+ g_free(s);
+ }
+}
+
+
+void
+gdm_putenv(gchar *s)
+{
+ putenv(s);
+ g_free(s);
+}
+
+
+/* EOF */
diff --git a/daemon/server.c b/daemon/server.c
new file mode 100644
index 00000000..bc293fa3
--- /dev/null
+++ b/daemon/server.c
@@ -0,0 +1,317 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This file contains functions for controlling local X servers */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <strings.h>
+#include <signal.h>
+#include <errno.h>
+#include <X11/Xlib.h>
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+extern gchar *GdmDisplayInit;
+extern gchar *GdmAuthDir;
+extern gchar *GdmLogDir;
+extern gint GdmXdmcp;
+
+extern gchar **gdm_arg_munch(const gchar *p);
+extern void gdm_auth_secure_display(GdmDisplay *);
+extern void gdm_debug(const gchar *, ...);
+extern void gdm_error(const gchar *, ...);
+extern gint gdm_display_manage(GdmDisplay *);
+extern void gdm_putenv(gchar *);
+extern void gdm_xdmcp_close();
+
+void gdm_server_start(GdmDisplay *d);
+void gdm_server_stop(GdmDisplay *d);
+void gdm_server_restart(GdmDisplay *d);
+void gdm_server_usr1_handler(gint);
+void gdm_server_alarm_handler(gint);
+GdmDisplay *gdm_server_alloc (gint id, gchar *command);
+
+
+GdmDisplay *d;
+sigset_t mask, omask;
+
+
+void
+gdm_server_start(GdmDisplay *disp)
+{
+ struct sigaction usr1;
+ sigset_t usr1mask;
+ int logfd;
+ gchar *srvcmd=NULL;
+ gchar **argv=NULL;
+
+ d=disp;
+
+ gdm_debug("gdm_server_start: %s", d->name);
+
+ /* Catch USR1 from X server */
+ usr1.sa_handler = gdm_server_usr1_handler;
+ usr1.sa_flags = SA_RESTART|SA_RESETHAND;
+ sigemptyset(&usr1.sa_mask);
+
+ if(sigaction(SIGUSR1, &usr1, NULL) < 0) {
+ gdm_error(_("gdm_server_start: Error setting up USR1 signal handler"));
+ exit(SERVER_ABORT);
+ }
+
+ sigemptyset(&usr1mask);
+ sigaddset(&usr1mask, SIGUSR1);
+ sigprocmask(SIG_UNBLOCK, &usr1mask, NULL);
+
+ /* Log all output from spawned programs to a file */
+ logfd=open(g_strconcat(GdmLogDir, "/", d->name, ".log", NULL),
+ O_CREAT|O_TRUNC|O_APPEND|O_WRONLY, 0666);
+
+ if(logfd != -1) {
+ dup2(logfd, 1);
+ dup2(logfd, 2);
+ }
+ else
+ gdm_error(_("gdm_server_start: Could not open logfile for display %s!"), d->name);
+
+ /* Just in case we have an old server hanging around */
+ if(d->servpid) {
+ gdm_debug("gdm_server_start: Old server found (%d). Killing.", d->servpid);
+ gdm_server_stop(d);
+ }
+
+ /* Secure display with cookie */
+ gdm_auth_secure_display(d);
+ gdm_putenv(g_strconcat("XAUTHORITY=", d->auth, NULL));
+ gdm_putenv(g_strconcat("DISPLAY=", d->name, NULL));
+
+ /* Fork into two processes. Parent remains the gdm slave
+ * process. Child becomes the X server.
+ */
+
+ switch(d->servpid=fork()) {
+
+ case 0:
+ /* Close the XDMCP fd inherited by the daemon process */
+ if(GdmXdmcp)
+ gdm_xdmcp_close();
+
+ /* The X server expects USR1 to be SIG_IGN */
+ usr1.sa_handler = SIG_IGN;
+ usr1.sa_flags = SA_RESTART;
+ sigemptyset(&usr1.sa_mask);
+
+ if(sigaction(SIGUSR1, &usr1, NULL) < 0) {
+ gdm_error(_("gdm_server_start: Error setting USR1 to SIG_IGN"));
+ exit(SERVER_ABORT);
+ }
+
+ srvcmd=g_strconcat(d->command, " -auth ", GdmAuthDir, \
+ "/", d->name, ".xauth ",
+ d->name, NULL);
+
+ gdm_debug("gdm_server_start: '%s'", srvcmd);
+
+ argv=gdm_arg_munch(srvcmd);
+ g_free(srvcmd);
+
+ setpgid(0, 0);
+
+ execv(argv[0], argv);
+
+ gdm_error(_("gdm_server_start: Xserver not found: %s"), d->command);
+
+ exit(SERVER_ABORT);
+ break;
+
+ case -1:
+ gdm_error(_("gdm_server_start: Can't fork Xserver process!"));
+ d->servpid=0;
+ break;
+
+ default:
+ break;
+ }
+
+ d->servstat=SERVER_STARTED;
+
+ /* Wait for X server to send ready signal */
+ pause();
+}
+
+
+void
+gdm_server_stop(GdmDisplay *d)
+{
+ gdm_debug("gdm_server_stop: Server for %s going down!", d->name);
+
+ kill(d->servpid, SIGTERM);
+ waitpid(d->servpid, 0, 0);
+ d->servpid=0;
+ d->servstat=SERVER_DEAD;
+
+ if(unlink(d->auth) == -1)
+ gdm_error(_("gdm_server_stop: Could not unlink auth file: %s!"), strerror(errno));
+}
+
+
+/* FIXME: We have a race here. What if USR1 is delivered before we enable the handler?
+ * This only succeeds because the X server takes ages to shut down...
+ * Maybe we should jump directly to display_manage and bail out on error?
+ * Needs thinking for sure...
+ */
+
+void
+gdm_server_restart(GdmDisplay *d)
+{
+ sigset_t usr1mask;
+ struct sigaction usr1, sigalarm;
+
+ gdm_debug("gdm_server_restart: Server for %s restarting!", d->name);
+
+ if(d->servpid && kill(d->servpid, 0)<0) {
+ gdm_debug("gdm_server_restart: Old server for %s still alive. Killing!", d->name);
+ gdm_server_stop(d);
+ gdm_server_start(d);
+ }
+
+ /* Create new cookie */
+ gdm_auth_secure_display(d);
+ gdm_putenv(g_strconcat("XAUTHORITY=", d->auth, NULL));
+ gdm_putenv(g_strconcat("DISPLAY=", d->name, NULL));
+
+ /* Catch USR1 from X server */
+ usr1.sa_handler = gdm_server_usr1_handler;
+ usr1.sa_flags = SA_RESTART|SA_RESETHAND;
+ sigemptyset(&usr1.sa_mask);
+
+ if(sigaction(SIGUSR1, &usr1, NULL) < 0) {
+ gdm_error(_("gdm_server_start: Error setting up USR1 signal handler"));
+ exit(SERVER_ABORT);
+ }
+
+ sigemptyset(&usr1mask);
+ sigaddset(&usr1mask, SIGUSR1);
+ sigprocmask(SIG_UNBLOCK, &usr1mask, NULL);
+
+ /* Reset X and force auth file reread. XCloseDisplay works on most servers but we play it safe */
+ /*gdm_debug("gdm_server_restart: Servpid=%d", d->servpid);*/
+ /*kill(d->servpid, SIGHUP);*/
+
+ d->servstat=SERVER_STARTED;
+
+ /* We add a timeout in case the X server fails to start. This
+ * might happen because X servers take a while to die, close their
+ * sockets etc. If the old X server isn't completely dead, the new
+ * one will fail and we'll hang here forever */
+
+ sigalarm.sa_handler = gdm_server_alarm_handler;
+ sigalarm.sa_flags = 0;
+ sigemptyset(&sigalarm.sa_mask);
+
+ if(sigaction(SIGALRM, &sigalarm, NULL) < 0) {
+ gdm_error(_("gdm_server_restart: Error setting up ALARM signal handler"));
+ return;
+ }
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &mask, &omask);
+
+ alarm(10);
+
+ /* Wait for X server to send ready signal */
+ pause();
+}
+
+
+void
+gdm_server_alarm_handler(gint signal)
+{
+ /* Unset alarm and try again */
+ alarm(0);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ waitpid(d->servpid, 0, WNOHANG);
+
+ gdm_debug("gdm_server_alarm_handler: Temporary server failure");
+ gdm_server_restart(d);
+}
+
+
+void
+gdm_server_usr1_handler(gint sig)
+{
+ sigset_t usr1mask;
+
+ /* Unset alarm */
+ alarm(0);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ gdm_debug("gdm_server_usr1_handler: Starting display %s!", d->name);
+
+ d->servstat=SERVER_RUNNING;
+
+ /* Block USR1 */
+ sigemptyset(&usr1mask);
+ sigaddset(&usr1mask, SIGUSR1);
+ sigprocmask(SIG_BLOCK, &usr1mask, NULL);
+
+ gdm_display_manage(d);
+}
+
+
+GdmDisplay *
+gdm_server_alloc (gint id, gchar *command)
+{
+ gchar dname[1024];
+
+ GdmDisplay *d = g_malloc(sizeof(GdmDisplay));
+
+ sprintf(dname, ":%d", id);
+ d->auth = NULL;
+ d->command = g_strdup(command);
+ d->cookie = NULL;
+ d->dispstat = DISPLAY_DEAD;
+ d->greetpid = 0;
+ d->id = id;
+ d->name = strdup(dname);
+ d->servpid = 0;
+ d->servstat = SERVER_DEAD;
+ d->sessionid = 0;
+ d->sesspid = 0;
+ d->slavepid = 0;
+ d->type = DISPLAY_LOCAL;
+ d->sessionid = 0;
+ d->acctime = 0;
+ d->dsp = NULL;
+
+ return (d);
+}
+
+
+/* EOF */
diff --git a/daemon/slave.c b/daemon/slave.c
new file mode 100644
index 00000000..235788ce
--- /dev/null
+++ b/daemon/slave.c
@@ -0,0 +1,615 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This is the gdm slave process. gdmslave runs the chooser, greeter
+ * and the user's session scripts.
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <strings.h>
+#include <X11/Xlib.h>
+#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+extern uid_t GdmUserId;
+extern gid_t GdmGroupId;
+extern gchar *GdmSessDir;
+extern gchar *GdmGreeter;
+extern gchar *GdmDisplayInit;
+extern gchar *GdmPreSession;
+extern gchar *GdmPostSession;
+extern gchar *GdmSuspend;
+extern gchar *GdmDefaultPath;
+extern gint GdmKillInitClients;
+extern gint GdmRetryDelay;
+
+extern gboolean gdm_file_check(gchar *caller, uid_t user, gchar *dir, gchar *file, gboolean absentok);
+extern gchar **gdm_arg_munch(const gchar *p);
+extern gint gdm_exec_script(GdmDisplay*, gchar *dir);
+extern void gdm_abort(const char*, ...);
+extern void gdm_error(const char*, ...);
+extern void gdm_debug(const char*, ...);
+extern void gdm_remanage(const char*, ...);
+extern void gdm_verify_cleanup (void);
+extern void gdm_auth_user_add(GdmDisplay *d, gchar *home);
+extern void gdm_auth_user_remove(GdmDisplay *d, gchar *home);
+extern void gdm_exec_command(gchar *cmd);
+extern void gdm_putenv(gchar *s);
+extern gchar *gdm_verify_user (gchar *display);
+
+void gdm_slave_start(GdmDisplay *d);
+static gint gdm_slave_xerror_handler(Display *disp, XErrorEvent *evt);
+static gint gdm_slave_xioerror_handler(Display *disp);
+static void gdm_slave_greeter(void);
+static void gdm_slave_session_start(gchar *login, gchar *session, gboolean savesess, gchar *lang, gboolean savelang);
+static void gdm_slave_session_stop(void);
+static void gdm_slave_session_cleanup(void);
+static void gdm_slave_term_handler(int sig);
+static void gdm_slave_child_handler(int sig);
+static void gdm_slave_windows_kill(void);
+static void gdm_slave_xsync_handler(int sig);
+static gboolean gdm_slave_xsync_ping(void);
+gchar *gdm_slave_greeter_ctl(gchar cmd, gchar *str);
+
+
+GdmDisplay *d;
+struct passwd *pwent;
+sigset_t mask, omask;
+gboolean pingack;
+gboolean greet=TRUE;
+FILE *greeter;
+
+
+void
+gdm_slave_start(GdmDisplay *display)
+{
+ struct sigaction term, child;
+ gint openretries=0;
+
+ gdm_debug("gdm_slave_start: Starting slave process for %s", display->name);
+
+ d=display;
+
+ gdm_putenv(g_strconcat("XAUTHORITY=", d->auth, NULL));
+ gdm_putenv(g_strconcat("DISPLAY=", d->name, NULL));
+
+ /* Handle a INT/TERM signals from gdm master */
+ term.sa_handler = gdm_slave_term_handler;
+ term.sa_flags = SA_RESTART;
+ sigemptyset(&term.sa_mask);
+ sigaddset(&term.sa_mask, SIGTERM);
+ sigaddset(&term.sa_mask, SIGINT);
+
+ if((sigaction(SIGTERM, &term, NULL) < 0) || (sigaction(SIGINT, &term, NULL) < 0))
+ gdm_abort(_("gdm_slave_init: Error setting up TERM/INT signal handler"));
+
+ /* Child handler. Keeps an eye on greeter/session */
+ child.sa_handler = gdm_slave_child_handler;
+ child.sa_flags = SA_RESTART|SA_NOCLDSTOP;
+ sigemptyset(&child.sa_mask);
+
+ if(sigaction(SIGCHLD, &child, NULL) < 0)
+ gdm_abort(_("gdm_slave_init: Error setting up CHLD signal handler"));
+
+ /* The signals we wish to listen to */
+ sigfillset(&mask);
+ sigdelset(&mask, SIGINT);
+ sigdelset(&mask, SIGTERM);
+ sigdelset(&mask, SIGCHLD);
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+
+ /* X error handlers to avoid the default ones: exit(1) */
+ XSetErrorHandler(gdm_slave_xerror_handler);
+ XSetIOErrorHandler(gdm_slave_xioerror_handler);
+
+ /* We keep our own (windowless) connection (dsp) open to avoid the
+ * X server resetting due to lack of active connections. */
+
+ gdm_debug("gdm_slave_start: Opening display %s", d->name);
+ d->dsp=NULL;
+
+ while(openretries < 10 && d->dsp==NULL) {
+ d->dsp=XOpenDisplay(d->name);
+
+ if(!d->dsp) {
+ gdm_debug("gdm_slave_start: Sleeping %d on a retry", openretries*2);
+ sleep(openretries*2);
+ openretries++;
+ }
+ }
+
+ if(d->dsp)
+ gdm_slave_greeter(); /* Start the greeter */
+ else
+ exit(DISPLAY_ABORT);
+}
+
+
+static void
+gdm_slave_greeter(void)
+{
+ gint pipe1[2], pipe2[2];
+ gchar *login=NULL, *session, *language;
+ gboolean savesess=FALSE, savelang=FALSE;
+ gchar **argv;
+
+ gdm_debug("gdm_slave_greeter: Running greeter on %s", d->name);
+
+ /* Run the init script. gdmslave suspends until script has terminated */
+ gdm_exec_script(d, GdmDisplayInit);
+
+ /* Open a pipe for greeter communications */
+ if(pipe(pipe1) < 0 || pipe(pipe2) < 0)
+ gdm_abort(_("gdm_slave_greeter: Can't init pipe to gdmgreeter"));
+
+ greet=TRUE;
+
+ /* Fork. Parent is gdmslave, child is greeter process. */
+ switch(d->greetpid=fork()) {
+
+ case 0:
+ sigfillset(&mask);
+ sigdelset(&mask, SIGINT);
+ sigdelset(&mask, SIGTERM);
+ sigdelset(&mask, SIGHUP);
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+
+ /* Plumbing */
+ close(pipe1[1]);
+ close(pipe2[0]);
+
+ if(pipe1[0] != STDIN_FILENO)
+ dup2(pipe1[0], STDIN_FILENO);
+
+ if(pipe2[1] != STDOUT_FILENO)
+ dup2(pipe2[1], STDOUT_FILENO);
+
+ if(setgid(GdmGroupId) < 0)
+ gdm_abort(_("gdm_slave_greeter: Couldn't set groupid to %d"), GdmGroupId);
+
+ if(setuid(GdmUserId) < 0)
+ gdm_abort(_("gdm_slave_greeter: Couldn't set userid to %d"), GdmUserId);
+
+ gdm_putenv(g_strconcat("XAUTHORITY=", d->auth, NULL));
+ gdm_putenv(g_strconcat("DISPLAY=", d->name, NULL));
+ gdm_putenv(g_strconcat("HOME=/", NULL)); /* Hack */
+ gdm_putenv(g_strconcat("PATH=", GdmDefaultPath, NULL));
+
+ argv=gdm_arg_munch(GdmGreeter);
+ execv(argv[0], argv);
+
+ gdm_abort(_("gdm_slave_greeter: Error starting greeter on display %s"), d->name);
+
+ case -1:
+ gdm_abort(_("gdm_slave_greeter: Can't fork gdmgreeter process"));
+
+ default:
+ close(pipe1[0]);
+ close(pipe2[1]);
+
+ if(pipe1[1] != STDOUT_FILENO)
+ dup2(pipe1[1], STDOUT_FILENO);
+
+ if(pipe2[0] != STDIN_FILENO)
+ dup2(pipe2[0], STDIN_FILENO);
+
+ greeter=fdopen(STDIN_FILENO, "r");
+
+ gdm_debug("gdm_slave_greeter: Greeter on pid %d", d->greetpid);
+ break;
+ }
+
+ /* Chat with greeter */
+ while(login==NULL) {
+ login=gdm_verify_user(d->name);
+
+ if(login==NULL) {
+ gdm_slave_greeter_ctl(GDM_RESET, "");
+ sleep(GdmRetryDelay);
+ }
+ }
+
+ session= gdm_slave_greeter_ctl(GDM_SESS, "");
+ language=gdm_slave_greeter_ctl(GDM_LANG, "");
+
+ if(strlen(gdm_slave_greeter_ctl(GDM_SSESS, "")))
+ savesess=TRUE;
+
+ if(strlen(gdm_slave_greeter_ctl(GDM_SLANG, "")))
+ savelang=TRUE;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, &omask);
+ greet=FALSE;
+
+ /* Kill greeter and wait for it to die */
+ kill(d->greetpid, SIGINT);
+ waitpid(d->greetpid, 0, 0);
+ d->greetpid=0;
+
+ sigprocmask(SIG_UNBLOCK, &omask, NULL);
+
+ if(GdmKillInitClients)
+ gdm_slave_windows_kill();
+
+ gdm_slave_session_start(login, session, savesess, language, savelang);
+}
+
+
+static void
+gdm_slave_session_start(gchar *login, gchar *session, gboolean savesess, gchar *lang, gboolean savelang)
+{
+ gchar *sessdir, *cfgdir, *cfgstr;
+ struct stat statbuf;
+
+ gdm_debug("gdm_slave_session_start: %s on %s", login, d->name);
+
+ pwent=getpwnam(login);
+
+ /* If the user doesn't exist, reset the X server and restart greeter */
+ if(!pwent)
+ gdm_remanage(_("gdm_slave_session_init: User '%s' not found. Aborting."), login);
+
+ gdm_putenv(g_strconcat("XAUTHORITY=", pwent->pw_dir, "/.Xauthority", NULL));
+ gdm_putenv(g_strconcat("DISPLAY=", d->name, NULL));
+ gdm_putenv(g_strconcat("LOGNAME=", login, NULL));
+ gdm_putenv(g_strconcat("USER=", login, NULL));
+ gdm_putenv(g_strconcat("USERNAME=", login, NULL));
+ gdm_putenv(g_strconcat("HOME=", pwent->pw_dir, NULL));
+ gdm_putenv(g_strconcat("GDMSESSION=", session, NULL));
+ gdm_putenv(g_strconcat("SHELL=", pwent->pw_shell, NULL));
+ gdm_putenv(g_strconcat("PATH=", GdmDefaultPath, NULL));
+
+ if(!strcasecmp(lang, "english"))
+ putenv("LANG=C");
+ else
+ gdm_putenv(g_strconcat("LANG=", lang, NULL));
+
+ /* If script fails reset X server and restart greeter */
+ if(gdm_exec_script(d, GdmPreSession) != EXIT_SUCCESS)
+ gdm_remanage(_("gdm_slave_session_init: Execution of PreSession script returned > 0. Aborting."));
+
+ switch(d->sesspid=fork()) {
+
+ case -1:
+ gdm_abort(_("gdm_slave_session_init: Error forking user session"));
+
+ case 0:
+ setpgid(0, 0);
+
+ umask(022);
+
+ if(setgid(pwent->pw_gid) < 0)
+ gdm_remanage(_("gdm_slave_session_init: Could not setgid %d. Aborting."), pwent->pw_gid);
+
+ if(initgroups(login, pwent->pw_gid) < 0)
+ gdm_remanage(_("gdm_slave_session_init: initgroups() failed for %s. Aborting."), login);
+
+ if(setuid(pwent->pw_uid) < 0)
+ gdm_remanage(_("gdm_slave_session_init: Could not become %s. Aborting."), login);
+
+ chdir(pwent->pw_dir);
+
+ /* Run sanity check on ~user/.Xauthority and setup cookie */
+ if(!gdm_file_check("gdm_slave_session_init", pwent->pw_uid, pwent->pw_dir, ".Xauthority", TRUE)) {
+ XCloseDisplay(d->dsp);
+ exit(DISPLAY_REMANAGE);
+ }
+
+ gdm_auth_user_add(d, pwent->pw_dir);
+
+ /* Check if ~user/.gnome exists. Create it otherwise. */
+ cfgdir=g_strconcat(pwent->pw_dir, "/.gnome", NULL);
+
+ if(stat(cfgdir, &statbuf) == -1) { /* FIXME: Maybe I need to be a bit paranoid here! */
+ mkdir(cfgdir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+ chmod(cfgdir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
+ }
+
+ /* Sanity check on ~user/.gnome/gdm */
+ if(!gdm_file_check("gdm_slave_session_init", pwent->pw_uid, cfgdir, "gdm", TRUE)) {
+ gdm_slave_session_cleanup();
+ XCloseDisplay(d->dsp);
+ exit(DISPLAY_REMANAGE);
+ }
+
+ g_free(cfgdir);
+
+ if(savesess) {
+ /* libgnome sets home to ~root, so we have to write the path ourselves */
+ cfgstr = g_strconcat("=", pwent->pw_dir, "/.gnome/gdm=/session/last", NULL);
+ gnome_config_set_string(cfgstr, session);
+ gnome_config_sync();
+ g_free(cfgstr);
+ }
+
+ if(savelang) {
+ cfgstr = g_strconcat("=", pwent->pw_dir, "/.gnome/gdm=/session/lang", NULL);
+ gnome_config_set_string(cfgstr, lang);
+ gnome_config_sync();
+ g_free(cfgstr);
+ }
+
+ sessdir = g_strconcat(GdmSessDir, "/", session, NULL);
+
+ gdm_debug("Running %s for %s on %s", sessdir, login, d->name);
+
+ /* Unblock SIGCHLD for broken terminals */
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
+ execl(sessdir, NULL);
+
+ gdm_error(_("gdm_slave_session_init: Could not start session `%s'"), sessdir);
+
+ gdm_slave_session_stop();
+ gdm_slave_session_cleanup();
+
+ exit(DISPLAY_REMANAGE);
+
+ default:
+ break;
+ }
+
+ waitpid(d->sesspid, 0, 0);
+
+ gdm_slave_session_stop();
+ gdm_slave_session_cleanup();
+}
+
+
+static void
+gdm_slave_session_stop(void)
+{
+ gdm_debug("gdm_slave_session_stop: %s on %s", pwent->pw_name, d->name);
+
+ kill(-(d->sesspid), SIGTERM);
+
+ gdm_verify_cleanup();
+
+ /* Remove display from ~user/.Xauthority */
+ setegid(pwent->pw_gid);
+ seteuid(pwent->pw_uid);
+
+ if(gdm_file_check("gdm_slave_session_stop", pwent->pw_uid, pwent->pw_dir, ".Xauthority", FALSE))
+ gdm_auth_user_remove(d, pwent->pw_dir);
+
+ setegid(GdmGroupId);
+ seteuid(0);
+}
+
+
+/* Only executed if display is still alive */
+static void
+gdm_slave_session_cleanup(void)
+{
+ gdm_debug("gdm_slave_session_cleanup: %s on %s", pwent->pw_name, d->name);
+
+ if(d->dsp && gdm_slave_xsync_ping()) {
+
+ /* Execute post session script */
+ gdm_debug("gdm_slave_session_cleanup: Running post session script");
+ gdm_exec_script(d, GdmPostSession);
+
+ /* Cleanup */
+ gdm_debug("gdm_slave_session_cleanup: Killing windows");
+ gdm_slave_windows_kill();
+
+ XCloseDisplay(d->dsp);
+ }
+
+ exit(DISPLAY_REMANAGE);
+}
+
+
+static void
+gdm_slave_term_handler(int sig)
+{
+ gdm_debug("gdm_slave_term_handler: %s got TERM signal", d->name);
+
+ if(d->greetpid) {
+ gdm_debug("gdm_slave_term_handler: Whacking greeter");
+ kill(d->greetpid, SIGINT);
+ waitpid(d->greetpid, 0, 0);
+ d->greetpid=0;
+ }
+ else if(pwent)
+ gdm_slave_session_stop();
+
+ gdm_debug("gdm_slave_term_handler: Whacking client connections");
+ gdm_slave_windows_kill();
+ XCloseDisplay(d->dsp);
+ exit(DISPLAY_ABORT);
+}
+
+
+/* Called on every SIGCHLD */
+static void
+gdm_slave_child_handler(int sig)
+{
+ gint status;
+ pid_t pid;
+
+ while((pid=waitpid(-1, &status, WNOHANG)) > 0) {
+ gdm_debug("gdm_slave_child_handler: %d died", pid);
+
+ if(WIFEXITED(status))
+ gdm_debug("gdm_slave_child_handler: %d returned %d", pid, WEXITSTATUS(status));
+
+ if(pid==d->greetpid && greet)
+ if(WIFEXITED(status))
+ exit(WEXITSTATUS(status));
+ else {
+ if(d && d->dsp)
+ XCloseDisplay(d->dsp);
+
+ exit(DISPLAY_REMANAGE);
+ }
+
+ if(pid==d->sesspid) {
+ gdm_slave_session_stop();
+ gdm_slave_session_cleanup();
+ }
+ }
+}
+
+
+/* Only kills clients, not connections. This keeps the server alive */
+static void
+gdm_slave_windows_kill(void)
+{
+ Window root, parent, *children;
+ gint child, screen, nchildren;
+ Display *disp=NULL;
+
+ disp=XOpenDisplay(d->name);
+
+ if(!disp) {
+ gdm_debug("gdm_slave_windows_kill: Could not open display %s", d->name);
+ return;
+ }
+
+ gdm_debug("gdm_slave_windows_kill: Killing windows on %s", d->name);
+
+ gdm_putenv(g_strconcat("XAUTHORITY=", d->auth, NULL));
+ gdm_putenv(g_strconcat("DISPLAY=", d->name, NULL));
+
+ for(screen=0 ; screen<ScreenCount(disp) ; screen++) {
+
+ nchildren=0;
+
+ while(XQueryTree(disp, RootWindow(disp, screen), &root, &parent,
+ &children, &nchildren) && nchildren>0) {
+
+ for(child=0 ; child<nchildren ; child++) {
+ gdm_debug("gdm_slave_windows_kill: Killing child 0x%x", children[child]);
+ XKillClient(disp, children[child]);
+ }
+
+ XFree(children);
+ }
+
+ }
+
+ XSync(disp, FALSE);
+}
+
+
+/* Minor X faults */
+static gint
+gdm_slave_xerror_handler(Display *disp, XErrorEvent *evt)
+{
+ gdm_debug("gdm_slave_windows_kill_error_handler: Blam");
+ pingack=FALSE;
+ return(TRUE);
+}
+
+
+/* We respond to fatal errors by restarting the display */
+static gint
+gdm_slave_xioerror_handler(Display *disp)
+{
+ gdm_debug("gdm_slave_xioerror_handler: I/O error for display %s", d->name);
+
+ if(pwent)
+ gdm_slave_session_stop();
+
+ gdm_error(_("gdm_slave_windows_kill_ioerror_handler: Fatal X error - Restarting %s"), d->name);
+
+ exit(DISPLAY_RESERVER);
+}
+
+
+static void
+gdm_slave_xsync_handler(int sig)
+{
+ gdm_debug("gdm_slave_xsync_handler: Xping failed for display %s", d->name);
+ pingack=FALSE;
+}
+
+
+static gboolean
+gdm_slave_xsync_ping(void)
+{
+ struct sigaction sigalarm;
+ sigset_t mask, omask;
+
+ gdm_debug("gdm_slave_xsync_ping: Pinging %s", d->name);
+
+ pingack=TRUE;
+
+ XSetErrorHandler(gdm_slave_xerror_handler);
+ XSetIOErrorHandler(gdm_slave_xioerror_handler);
+
+ sigalarm.sa_handler = gdm_slave_xsync_handler;
+ sigalarm.sa_flags = 0;
+ sigemptyset(&sigalarm.sa_mask);
+
+ if(sigaction(SIGALRM, &sigalarm, NULL) < 0)
+ gdm_abort(_("gdm_slave_xsync_ping: Error setting up ALARM signal handler"));
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &mask, &omask);
+
+ alarm(10);
+
+ XSync(d->dsp, TRUE);
+
+ alarm(0);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ gdm_debug("gdm_slave_xsync_ping: %s returned %d", d->name, pingack);
+
+ return(pingack);
+}
+
+
+gchar *
+gdm_slave_greeter_ctl(gchar cmd, gchar *str)
+{
+ gchar buf[FIELD_SIZE];
+
+ g_print("%c%s\n", cmd, str);
+
+ fgets(buf, FIELD_SIZE-1, greeter);
+
+ if(strlen(buf)) {
+ buf[strlen(buf)-1]='\0';
+ return(g_strndup(buf, strlen(buf)));
+ }
+ else
+ return(NULL);
+}
+
+/* EOF */
diff --git a/daemon/verify.c b/daemon/verify.c
new file mode 100644
index 00000000..5c5de89b
--- /dev/null
+++ b/daemon/verify.c
@@ -0,0 +1,271 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <pwd.h>
+#include <glib.h>
+#include <crypt.h>
+#include <config.h>
+#include <gnome.h>
+
+#ifdef HAVE_PAM
+ #include <security/pam_appl.h>
+#endif /* HAVE_PAM */
+
+#ifdef HAVE_SHADOW
+ #include <shadow.h>
+#endif /* HAVE_SHADOW */
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+extern void gdm_abort(const char*, ...);
+extern void gdm_debug(const char*, ...);
+extern void gdm_error(const char*, ...);
+extern gchar *gdm_slave_greeter_ctl(gchar cmd, gchar *str);
+
+extern gboolean GdmVerboseAuth;
+extern gboolean GdmAllowRoot;
+
+gchar *gdm_verify_user (gchar *display);
+void gdm_verify_cleanup (void);
+
+
+#ifdef HAVE_PAM
+
+pam_handle_t *pamh;
+
+
+static gint
+gdm_verify_pam_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp,
+ void *appdata_ptr)
+{
+ gint replies = 0;
+ struct pam_response *reply = NULL;
+ gchar *s;
+
+ reply=g_new0(struct pam_response, num_msg);
+
+ if(!reply)
+ return PAM_CONV_ERR;
+
+ for(replies=0; replies<num_msg; replies++) {
+
+ switch(msg[replies]->msg_style) {
+
+ case PAM_PROMPT_ECHO_ON:
+ s=gdm_slave_greeter_ctl(GDM_PROMPT, (gchar *)msg[replies]->msg);
+ reply[replies].resp_retcode=PAM_SUCCESS;
+ reply[replies].resp=g_strdup(s);
+ g_free(s);
+ break;
+
+ case PAM_PROMPT_ECHO_OFF:
+ s=gdm_slave_greeter_ctl(GDM_NOECHO, (gchar *)msg[replies]->msg);
+ reply[replies].resp_retcode=PAM_SUCCESS;
+ reply[replies].resp=g_strdup(s);
+ g_free(s);
+ break;
+
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ gdm_slave_greeter_ctl(GDM_MSGERR, (gchar *)msg[replies]->msg);
+ reply[replies].resp_retcode=PAM_SUCCESS;
+ reply[replies].resp=NULL;
+ break;
+
+ default:
+ g_free(reply);
+ return PAM_CONV_ERR;
+ }
+
+ }
+
+ *resp=reply;
+ return(PAM_SUCCESS);
+}
+
+
+static struct pam_conv pamc = {
+ &gdm_verify_pam_conv,
+ NULL
+};
+
+
+gchar *
+gdm_verify_user (gchar *display)
+{
+ gint pamerr;
+ gchar *login;
+ struct passwd *pwent;
+
+ login=gdm_slave_greeter_ctl(GDM_PROMPT, _("Login:"));
+
+ if(!login)
+ return(NULL);
+
+ pwent=getpwnam(login);
+
+ if(!pwent) {
+ gdm_error(_("Couldn't authenticate %s"), login);
+
+ if(GdmVerboseAuth)
+ gdm_slave_greeter_ctl(GDM_MSGERR, _("User unknown"));
+
+ return(NULL);
+ }
+
+ if(GdmAllowRoot && pwent->pw_uid == 0) {
+ gdm_error(_("Root login disallowed on display '%s'"), display);
+
+ if(GdmVerboseAuth)
+ gdm_slave_greeter_ctl(GDM_MSGERR, _("Root login disallowed"));
+
+ return(NULL);
+ }
+
+ if((pamerr=pam_start("gdm", login, &pamc, &pamh)) != PAM_SUCCESS) {
+ gdm_error(_("Can't find /etc/pam.d/gdm!"));
+ }
+
+ if((pamerr=pam_set_item(pamh, PAM_TTY, display)) != PAM_SUCCESS) {
+ gdm_error(_("Can't set PAM_TTY=%s"), ":0");
+ goto pamerr;
+ }
+
+ if((pamerr=pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
+ gdm_error(_("Couldn't authenticate %s"), login);
+ goto pamerr;
+ }
+
+ if((pamerr=pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
+ gdm_error(_("Couldn't set acct. mgmt for %s"), login);
+ goto pamerr;
+ }
+
+ if((pamerr=pam_setcred(pamh, 0)) != PAM_SUCCESS) {
+ gdm_error(_("Couldn't set credentials for %s"), login);
+ goto pamerr;
+ }
+
+ if((pamerr=pam_open_session(pamh, 0)) != PAM_SUCCESS) {
+ gdm_error(_("Couldn't open session for %s"), login);
+ goto pamerr;
+ }
+
+ return(login);
+
+ pamerr:
+
+ if(GdmVerboseAuth)
+ gdm_slave_greeter_ctl(GDM_MSGERR, (gchar *)pam_strerror(pamh, pamerr));
+
+ pam_end(pamh, pamerr);
+ pamh=NULL;
+
+ /* Workaround to avoid gdm messages being logged as PAM_pwdb */
+ closelog();
+ openlog("gdm", LOG_PID, LOG_DAEMON);
+
+ return(NULL);
+}
+
+#else /* HAVE_PAM */
+
+gchar *
+gdm_verify_user (gchar *display)
+{
+ gchar *login, *passwd, *ppasswd;
+ struct passwd *pwent;
+
+#ifdef HAVE_SHADOW
+ struct spwd *sp;
+#endif
+
+ login=gdm_slave_greeter_ctl(GDM_PROMPT, _("Login:"));
+ pwent=getpwnam(login);
+
+ if(!pwent) {
+ gdm_error(_("Couldn't authenticate %s"), login);
+
+ if(GdmVerboseAuth)
+ gdm_slave_greeter_ctl(GDM_MSGERR, _("User unknown"));
+
+ return(NULL);
+ }
+
+ if(GdmAllowRoot && pwent->pw_uid == 0) {
+ gdm_error(_("Root login disallowed on display '%s'"), display);
+
+ if(GdmVerboseAuth)
+ gdm_slave_greeter_ctl(GDM_MSGERR, _("Root login disallowed"));
+
+ return(NULL);
+ }
+
+ ppasswd=!pwent ? NULL : pwent->pw_passwd;
+
+#ifdef HAVE_SHADOW
+ sp=getspnam(login);
+
+ if(sp)
+ ppasswd=sp->sp_pwdp;
+
+ endspent();
+#endif /* HAVE_SHADOW */
+
+ passwd=gdm_slave_greeter_ctl(GDM_NOECHO, _("Password:"));
+
+ if (!passwd || !ppasswd || strcmp(crypt(passwd, ppasswd), ppasswd)) {
+
+ if(GdmVerboseAuth)
+ gdm_slave_greeter_ctl(GDM_MSGERR, _("Incorrect password"));
+
+ return(NULL);
+ }
+
+ return(login);
+}
+#endif /* HAVE_PAM */
+
+
+void
+gdm_verify_cleanup (void)
+{
+#ifdef HAVE_PAM
+ gdm_debug("gdm_verify_cleanup: Closing session %d", pamh);
+
+ if(pamh) {
+ pam_close_session(pamh, 0);
+ pam_end(pamh, PAM_SUCCESS);
+ pamh=NULL;
+ }
+
+ /* Workaround to avoid gdm messages being logged as PAM_pwdb */
+ closelog();
+ openlog("gdm", LOG_PID, LOG_DAEMON);
+#endif /* HAVE_PAM */
+}
+
+/* EOF */
diff --git a/daemon/xdmcp.c b/daemon/xdmcp.c
new file mode 100644
index 00000000..b809a055
--- /dev/null
+++ b/daemon/xdmcp.c
@@ -0,0 +1,854 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@mkp.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 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* This file contains the XDMCP implementation for managing remote
+ * displays.
+ */
+
+/* Theory of operation:
+ *
+ * Process idles waiting for UDP packets on port 177.
+ * Incoming packets are decoded and checked against tcp_wrapper.
+ *
+ * A typical session looks like this:
+ *
+ * Display sends Query/BroadcastQuery to Manager.
+ *
+ * Manager selects an appropriate authentication scheme from the
+ * display's list of supported ones and sends Willing/Unwilling.
+ *
+ * Assuming the display accepts the auth. scheme it sends back a
+ * Request.
+ *
+ * If the manager accepts to service the display (i.e. loadavg is low)
+ * it sends back an Accept containing a unique SessionID. The
+ * SessionID is stored in an accept queue by the Manager. Should the
+ * manager refuse to start a session a Decline is sent to the display.
+ *
+ * The display returns a Manage request containing the supplied
+ * SessionID. The manager will then start a session on the display. In
+ * case the SessionID is not on the accept queue the manager returns
+ * Refuse. If the manager fails to open the display for connections
+ * Failed is returned.
+ *
+ * During the session the display periodically sends KeepAlive packets
+ * to the manager. The manager responds with Alive.
+ *
+ * Similarly the manager xpings the display once in a while and shuts
+ * down the connection on failure.
+ *
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#include <X11/Xdmcp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef HAVE_TCPWRAPPERS
+ #include <tcpd.h>
+#endif
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+int XdmcpReallocARRAY8 (ARRAY8Ptr array, int length);
+
+/* TCP Wrapper syslog control */
+gint allow_severity = LOG_INFO;
+gint deny_severity = LOG_WARNING;
+
+gint xdmcpfd;
+gint globsessid;
+gint pending=0;
+static ARRAY8 servhost;
+static XdmcpBuffer buf;
+
+extern GSList *displays;
+extern gint sessions;
+extern gchar *GdmLogDir;
+
+/* Tunables */
+extern gint GdmMaxPending; /* only accept this number of pending sessions */
+extern gint GdmMaxManageWait; /* Dispose sessions not responding with MANAGE after 10 secs */
+extern gint GdmMaxSessions; /* Maximum number of remote sessions */
+extern gint GdmPort; /* UDP port number */
+
+/*
+ * We don't support XDM-AUTHENTICATION-1 and XDM-AUTHORIZATION-1.
+ *
+ * The latter would be quite useful to avoid sending unencrypted
+ * cookies over the wire. Unfortunately it isn't supported without
+ * XDM-AUTHENTICATION-1 which requires a key database with private
+ * keys from all X terminals on your LAN. Fun, fun, fun.
+ *
+ * Furthermore user passwords go over the wire in cleartext anyway so
+ * protecting cookies is not that important.
+ */
+
+typedef struct _XdmAuth {
+ ARRAY8 authentication;
+ ARRAY8 authorization;
+} XdmAuthRec, *XdmAuthPtr;
+
+static XdmAuthRec serv_authlist = {
+ { (CARD16) 0, (CARD8 *) 0 },
+ { (CARD16) 0, (CARD8 *) 0 }
+};
+
+
+extern gchar *gdm_cookie_generate(void);
+extern void gdm_abort(const gchar *format, ...);
+extern void gdm_debug(const gchar *format, ...);
+extern void gdm_error(const gchar *format, ...);
+extern void gdm_putenv(gchar *s);
+extern void gdm_auth_secure_display(GdmDisplay *d);
+extern gint gdm_display_manage(GdmDisplay *d);
+extern void gdm_display_dispose(GdmDisplay *d);
+
+int gdm_xdmcp_init(void);
+void gdm_xdmcp_run(void);
+void gdm_xdmcp_close(void);
+static void gdm_xdmcp_decode_packet (void);
+static void gdm_xdmcp_handle_query (struct sockaddr_in *clnt_sa, gint len, gint type);
+static void gdm_xdmcp_handle_request(struct sockaddr_in *clnt_sa, gint len);
+static void gdm_xdmcp_handle_manage (struct sockaddr_in *clnt_sa, gint len);
+static void gdm_xdmcp_handle_keepalive (struct sockaddr_in *clnt_sa, gint len);
+static void gdm_xdmcp_send_willing (struct sockaddr_in *clnt_sa);
+static void gdm_xdmcp_send_unwilling(struct sockaddr_in *clnt_sa, gint type);
+static void gdm_xdmcp_send_accept (struct sockaddr_in *clnt_sa, gint displaynum);
+static void gdm_xdmcp_send_decline (struct sockaddr_in *clnt_sa);
+static void gdm_xdmcp_send_refuse (struct sockaddr_in *clnt_sa, CARD32 sessid);
+static void gdm_xdmcp_send_failed (struct sockaddr_in *clnt_sa, CARD32 sessid);
+static void gdm_xdmcp_send_alive (struct sockaddr_in *clnt_sa, CARD32 sessid);
+static gboolean gdm_xdmcp_host_allow(struct sockaddr_in *cnlt_sa);
+static GdmDisplay *gdm_xdmcp_display_alloc (struct sockaddr_in *, gint);
+static GdmDisplay *gdm_xdmcp_display_lookup(CARD32 sessid);
+static void gdm_xdmcp_display_dispose_check(gchar *name);
+static void gdm_xdmcp_displays_check(void);
+
+
+int
+gdm_xdmcp_init(void)
+{
+ struct sockaddr_in serv_sa;
+ gchar hostbuf[256];
+
+ globsessid=time(NULL);
+
+ /* Fetch and store local hostname in XDMCP friendly format */
+ if(gethostname(hostbuf, 255))
+ gdm_abort(_("gdm_xdmcp_init: Could not get server hostname: %s!"), strerror(errno));
+
+ servhost.data=g_strdup(hostbuf);
+ servhost.length=strlen(servhost.data);
+
+ gdm_debug("Start up on host %s, port %d", hostbuf, GdmPort);
+
+ /* Open socket for communications */
+ xdmcpfd = socket(AF_INET, SOCK_DGRAM, 0); /* UDP */
+
+ if(xdmcpfd == -1)
+ gdm_abort(_("gdm_xdmcp_init: Could not create socket!"));
+
+ serv_sa.sin_family = AF_INET;
+ serv_sa.sin_port = htons (GdmPort); /* UDP 177 */
+ serv_sa.sin_addr.s_addr = htonl (INADDR_ANY);
+
+ if(bind(xdmcpfd, (struct sockaddr_in *) &serv_sa, sizeof(serv_sa)) == -1)
+ gdm_abort(_("gdm_xdmcp_init: Could not bind to XDMCP socket!"));
+
+ return (0);
+}
+
+
+void
+gdm_xdmcp_run(void)
+{
+ GIOChannel *channel;
+
+ channel = g_io_channel_unix_new(xdmcpfd);
+ g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
+ G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ (GIOFunc) gdm_xdmcp_decode_packet,
+ GINT_TO_POINTER(xdmcpfd), NULL);
+ g_io_channel_unref(channel);
+}
+
+
+void
+gdm_xdmcp_close(void)
+{
+ close(xdmcpfd);
+}
+
+
+static void
+gdm_xdmcp_decode_packet(void)
+{
+ struct sockaddr_in clnt_sa;
+ gint sa_len=sizeof(clnt_sa);
+ XdmcpHeader header;
+
+ if(!XdmcpFill(xdmcpfd, &buf, &clnt_sa, &sa_len)) {
+ gdm_error(_("gdm_xdmcp_decode: Could not create XDMCP buffer!"));
+ return;
+ }
+
+ if(!XdmcpReadHeader(&buf, &header)) {
+ gdm_error(_("gdm_xdmcp_decode: Could not read XDMCP header!"));
+ return;
+ }
+
+ if(header.version != XDM_PROTOCOL_VERSION) {
+ gdm_error(_("gdm_xdmcp_decode: Incorrect XDMCP version!"));
+ return;
+ }
+
+ switch(header.opcode) {
+
+ case BROADCAST_QUERY:
+ gdm_xdmcp_handle_query(&clnt_sa, header.length, BROADCAST_QUERY);
+ break;
+
+ case QUERY:
+ gdm_xdmcp_handle_query(&clnt_sa, header.length, QUERY);
+ break;
+
+ case INDIRECT_QUERY:
+ break;
+
+ case FORWARD_QUERY:
+ break;
+
+ case REQUEST:
+ /* Free pending displays if */
+ gdm_xdmcp_displays_check();
+
+ gdm_xdmcp_handle_request(&clnt_sa, header.length);
+ break;
+
+ case MANAGE:
+ gdm_xdmcp_handle_manage(&clnt_sa, header.length);
+ break;
+
+ case KEEPALIVE:
+ gdm_xdmcp_handle_keepalive(&clnt_sa, header.length);
+ break;
+
+ default:
+ gdm_error(_("gdm_xdmcp_decode_packet: Unknown opcode from host %s"),
+ inet_ntoa(clnt_sa.sin_addr));
+ break;
+ }
+}
+
+
+static void
+gdm_xdmcp_handle_query(struct sockaddr_in *clnt_sa, gint len, gint type)
+{
+ ARRAYofARRAY8 clnt_authlist;
+ gint i, explen=1;
+
+ gdm_debug("gdm_xdmcp_query: Opcode %d from %s",
+ type, inet_ntoa(clnt_sa->sin_addr));
+
+ /* Extract array of authentication names from Xdmcp packet */
+ if(!XdmcpReadARRAYofARRAY8(&buf, &clnt_authlist)) {
+ gdm_error(_("gdm_xdmcp_query: Could not extract authlist from packet"));
+ return;
+ }
+
+ /* Crude checksumming */
+ for(i=0 ; i<clnt_authlist.length ; i++) {
+ gdm_debug("gdm_xdmcp_query: authlist: %s", clnt_authlist.data);
+ explen += 2+clnt_authlist.data[i].length;
+ }
+
+ if(len!=explen) {
+ gdm_error(_("gdm_xdmcp_query: Error in checksum"));
+ return;
+ }
+
+ /* Don't negotiate authentication - Unsupported */
+ XdmcpDisposeARRAYofARRAY8(&clnt_authlist);
+
+ /* Check with tcp_wrappers if client is allowed to access */
+ if(gdm_xdmcp_host_allow(clnt_sa))
+ gdm_xdmcp_send_willing(clnt_sa);
+ else
+ gdm_xdmcp_send_unwilling(clnt_sa, type);
+}
+
+
+static void
+gdm_xdmcp_send_willing(struct sockaddr_in *clnt_sa)
+{
+ ARRAY8 status;
+ XdmcpHeader header;
+
+ gdm_debug("gdm_xdmcp_send_willing: Sending WILLING to %s", inet_ntoa(clnt_sa->sin_addr));
+
+ status.data=_("GNOME");
+ status.length=strlen(status.data);
+
+ header.opcode = (CARD16) WILLING;
+ header.length = 6 + serv_authlist.authentication.length;
+ header.length += servhost.length + status.length;
+ header.version = XDM_PROTOCOL_VERSION;
+ XdmcpWriteHeader (&buf, &header);
+
+ XdmcpWriteARRAY8 (&buf, &serv_authlist.authentication); /* Hardcoded authentication */
+ XdmcpWriteARRAY8 (&buf, &servhost);
+ XdmcpWriteARRAY8 (&buf, &status);
+ XdmcpFlush (xdmcpfd, &buf, clnt_sa, sizeof(struct sockaddr_in));
+}
+
+
+static void
+gdm_xdmcp_send_unwilling(struct sockaddr_in *clnt_sa, gint type)
+{
+ ARRAY8 status;
+ XdmcpHeader header;
+
+ gdm_debug("gdm_xdmcp_send_unwilling: Sending UNWILLING to %s", inet_ntoa(clnt_sa->sin_addr));
+
+ gdm_error(_("Denied XDMCP query from host %s"), inet_ntoa(clnt_sa->sin_addr));
+
+ status.data=_("Display not authorized to connect");
+ status.length=strlen(status.data);
+
+ header.opcode = (CARD16) UNWILLING;
+ header.length = 4 + servhost.length + status.length;
+ header.version = XDM_PROTOCOL_VERSION;
+ XdmcpWriteHeader (&buf, &header);
+
+ XdmcpWriteARRAY8 (&buf, &servhost);
+ XdmcpWriteARRAY8 (&buf, &status);
+ XdmcpFlush (xdmcpfd, &buf, clnt_sa, sizeof(struct sockaddr_in));
+}
+
+
+static void
+gdm_xdmcp_handle_request(struct sockaddr_in *clnt_sa, gint len)
+{
+ static CARD16 clnt_dspnum;
+ static ARRAY16 clnt_conntyp;
+ static ARRAYofARRAY8 clnt_addr;
+ static ARRAY8 clnt_authname;
+ static ARRAY8 clnt_authdata;
+ static ARRAYofARRAY8 clnt_authorization;
+ static ARRAY8 clnt_manufacturer;
+ gint explen;
+ gint i;
+ gboolean mitauth=FALSE;
+
+ gdm_debug("gdm_xdmcp_handle_request: Got REQUEST from %s",
+ inet_ntoa(clnt_sa->sin_addr));
+
+ /* Check with tcp_wrappers if client is allowed to access */
+ if(!gdm_xdmcp_host_allow(clnt_sa)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Got REQUEST from banned host %s"),
+ inet_ntoa(clnt_sa->sin_addr));
+ return;
+ }
+
+ /* Remote display number */
+ if(!XdmcpReadCARD16(&buf, &clnt_dspnum)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Could not read Display Number"));
+ return;
+ }
+
+ /* We don't care about connection type. Address says it all */
+ if(!XdmcpReadARRAY16(&buf, &clnt_conntyp)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Could not read Connection Type"));
+ return;
+ }
+
+ /* This is TCP/IP - we don't care */
+ if(!XdmcpReadARRAYofARRAY8 (&buf, &clnt_addr)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Could not read Client Address"));
+ return;
+ }
+
+ /* Read authentication type */
+ if(!XdmcpReadARRAY8 (&buf, &clnt_authname)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Could not read Authentication Names"));
+ return;
+ }
+
+ /* Read authentication data */
+ if(!XdmcpReadARRAY8 (&buf, &clnt_authdata)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Could not read Authentication Data"));
+ return;
+ }
+
+ /* Read and select from supported authorization list */
+ if(!XdmcpReadARRAYofARRAY8(&buf, &clnt_authorization)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Could not read Authorization List"));
+ return;
+ }
+
+ /* libXdmcp doesn't terminate strings properly so we cheat and use strncmp() */
+ for(i=0 ; i<clnt_authorization.length ; i++)
+ if(!strncmp(clnt_authorization.data[i].data, "MIT-MAGIC-COOKIE-1", 18))
+ mitauth=TRUE;
+
+ /* Manufacturer ID */
+ if(!XdmcpReadARRAY8 (&buf, &clnt_manufacturer)) {
+ gdm_error(_("gdm_xdmcp_handle_request: Could not read Manufacturer ID"));
+ return;
+ }
+
+ /* Crude checksumming */
+ explen = 2; /* Display Number */
+ explen += 1+2*clnt_conntyp.length; /* Connection Type */
+ explen += 1; /* Connection Address */
+ for(i=0 ; i<clnt_addr.length ; i++)
+ explen += 2+clnt_addr.data[i].length;
+ explen += 2+clnt_authname.length; /* Authentication Name */
+ explen += 2+clnt_authdata.length; /* Authentication Data */
+ explen += 1; /* Authorization Names */
+ for(i=0 ; i<clnt_authorization.length ; i++)
+ explen += 2+clnt_authorization.data[i].length;
+ explen += 2+clnt_manufacturer.length;
+
+ if(explen != len) {
+ gdm_error(_("gdm_xdmcp_handle_request: Failed checksum from %s"),
+ inet_ntoa(clnt_sa->sin_addr));
+ return;
+ }
+
+ gdm_debug("gdm_xdmcp_handle_request: pending=%d, MaxPending=%d, sessions=%d, MaxSessions=%d",
+ pending, GdmMaxPending, sessions, GdmMaxSessions);
+
+ /* if load<maxload */
+ if(mitauth &&
+ pending < GdmMaxPending &&
+ sessions < GdmMaxSessions)
+ gdm_xdmcp_send_accept(clnt_sa, clnt_dspnum);
+ else
+ gdm_xdmcp_send_decline(clnt_sa);
+}
+
+
+static void
+gdm_xdmcp_send_accept(struct sockaddr_in *clnt_sa, gint displaynum)
+{
+ XdmcpHeader header;
+ ARRAY8 authentype;
+ ARRAY8 authendata;
+ ARRAY8 authname;
+ ARRAY8 authdata;
+ GdmDisplay *d;
+
+ d=gdm_xdmcp_display_alloc(clnt_sa, displaynum);
+
+ authentype.data=(CARD8 *) 0;
+ authentype.length=(CARD16) 0;
+
+ authendata.data=(CARD8 *) 0;
+ authendata.length=(CARD16) 0;
+
+ authname.data="MIT-MAGIC-COOKIE-1";
+ authname.length=strlen(authname.data);
+
+ authdata.data=d->bcookie;
+ authdata.length=strlen(d->bcookie); /* I.e. 16 */
+
+ header.version=XDM_PROTOCOL_VERSION;
+ header.opcode=(CARD16) ACCEPT;
+ header.length = 4;
+ header.length += 2 + authentype.length;
+ header.length += 2 + authendata.length;
+ header.length += 2 + authname.length;
+ header.length += 2 + authdata.length;
+
+ XdmcpWriteHeader (&buf, &header);
+
+ XdmcpWriteCARD32 (&buf, d->sessionid);
+ XdmcpWriteARRAY8 (&buf, &authentype);
+ XdmcpWriteARRAY8 (&buf, &authendata);
+ XdmcpWriteARRAY8 (&buf, &authname);
+ XdmcpWriteARRAY8 (&buf, &authdata);
+
+ XdmcpFlush (xdmcpfd, &buf, clnt_sa, sizeof(struct sockaddr_in));
+
+ gdm_debug("gdm_xdmcp_send_accept: Sending ACCEPT to %s with SessionID=%d",
+ inet_ntoa(clnt_sa->sin_addr), d->sessionid);
+}
+
+
+static void
+gdm_xdmcp_send_decline(struct sockaddr_in *clnt_sa)
+{
+ XdmcpHeader header;
+ ARRAY8 authentype;
+ ARRAY8 authendata;
+ ARRAY8 status;
+
+ gdm_debug("gdm_xdmcp_send_decline: Sending DECLINE to %s",
+ inet_ntoa(clnt_sa->sin_addr));
+
+ authentype.data=(CARD8 *) 0;
+ authentype.length=(CARD16) 0;
+
+ authendata.data=(CARD8 *) 0;
+ authendata.length=(CARD16) 0;
+
+ status.data="Service refused";
+ status.length=strlen(status.data);
+
+ header.version=XDM_PROTOCOL_VERSION;
+ header.opcode=(CARD16) DECLINE;
+ header.length = 2 + status.length;
+ header.length += 2 + authentype.length;
+ header.length += 2 + authendata.length;
+ XdmcpWriteHeader (&buf, &header);
+
+ XdmcpWriteARRAY8 (&buf, &status);
+ XdmcpWriteARRAY8 (&buf, &authentype);
+ XdmcpWriteARRAY8 (&buf, &authendata);
+
+ XdmcpFlush (xdmcpfd, &buf, clnt_sa, sizeof(struct sockaddr_in));
+}
+
+
+static void
+gdm_xdmcp_handle_manage(struct sockaddr_in *clnt_sa, gint len)
+{
+ CARD32 clnt_sessid;
+ CARD16 clnt_dspnum;
+ static ARRAY8 clnt_dspclass;
+ GdmDisplay *d;
+ gint logfd;
+
+ gdm_debug("gdm_xdmcp_manage: Got MANAGE from %s", inet_ntoa(clnt_sa->sin_addr));
+
+ /* if (RcvSessId == SavedSessId) { run session }
+ elseif (SessId already in use) { nop; }
+ else { send refuse };
+ */
+
+ /* Check with tcp_wrappers if client is allowed to access */
+ if(!gdm_xdmcp_host_allow(clnt_sa)) {
+ gdm_error(_("gdm_xdmcp_handle_manage: Got Manage from banned host %s"),
+ inet_ntoa(clnt_sa->sin_addr));
+ return;
+ }
+
+ /* SessionID */
+ if(!XdmcpReadCARD32(&buf, &clnt_sessid)) {
+ gdm_error(_("gdm_xdmcp_handle_manage: Could not read Session ID"));
+ return;
+ }
+
+ /* Remote display number */
+ if(!XdmcpReadCARD16(&buf, &clnt_dspnum)) {
+ gdm_error(_("gdm_xdmcp_handle_manage: Could not read Display Number"));
+ return;
+ }
+
+ gdm_debug("gdm_xdmcp_manage: Got Display=%d, SessionID=%d from %s",
+ clnt_dspnum, clnt_sessid, inet_ntoa(clnt_sa->sin_addr));
+
+ /* Display Class */
+ if(!XdmcpReadARRAY8(&buf, &clnt_dspclass)) {
+ gdm_error(_("gdm_xdmcp_manage: Could not read Display Class"));
+ return;
+ }
+
+ d=gdm_xdmcp_display_lookup(clnt_sessid);
+
+ if(d && d->dispstat==XDMCP_PENDING) {
+
+ gdm_debug("gdm_xdmcp_handle_manage: Looked up %s", d->name);
+
+ /* Log all output from spawned programs to a file */
+ logfd=open(g_strconcat(GdmLogDir, "/", d->name, ".log", NULL),
+ O_CREAT|O_TRUNC|O_APPEND|O_WRONLY, 0666);
+
+ if(logfd != -1) {
+ dup2(logfd, 1);
+ dup2(logfd, 2);
+ }
+ else
+ gdm_error(_("gdm_xdmcp_handle_manage: Could not open logfile for display %s!"), d->name);
+
+ d->dispstat=XDMCP_MANAGED;
+ sessions++;
+ pending--;
+
+ /* Start greeter/session */
+ if(!gdm_display_manage(d)) {
+ gdm_xdmcp_send_failed(clnt_sa, clnt_sessid);
+ return;
+ }
+ }
+ else if (d && d->dispstat==XDMCP_MANAGED) {
+ gdm_debug("gdm_xdmcp_handle_manage: Session id %d already managed", clnt_sessid);
+ }
+ else {
+ gdm_debug("gdm_xdmcp_handle_manage: Failed to look up session id %d", clnt_sessid);
+ gdm_xdmcp_send_refuse(clnt_sa, clnt_sessid);
+ }
+}
+
+
+static void
+gdm_xdmcp_send_refuse(struct sockaddr_in *clnt_sa, CARD32 sessid)
+{
+ XdmcpHeader header;
+
+ gdm_debug("gdm_xdmcp_send_refuse: Sending REFUSE to %d", sessid);
+
+ header.version=XDM_PROTOCOL_VERSION;
+ header.opcode=(CARD16) REFUSE;
+ header.length=4;
+
+ XdmcpWriteHeader(&buf, &header);
+ XdmcpWriteCARD32(&buf, sessid);
+ XdmcpFlush(xdmcpfd, &buf, clnt_sa, sizeof(struct sockaddr_in));
+}
+
+
+static void
+gdm_xdmcp_send_failed(struct sockaddr_in *clnt_sa, CARD32 sessid)
+{
+ XdmcpHeader header;
+ ARRAY8 status;
+
+ gdm_debug("gdm_xdmcp_send_failed: Sending FAILED to %d", sessid);
+
+ status.data=g_strdup("Failed to start session");
+ status.length=strlen(status.data);
+
+ header.version=XDM_PROTOCOL_VERSION;
+ header.opcode=(CARD16) FAILED;
+ header.length=6+status.length;
+
+ XdmcpWriteHeader(&buf, &header);
+ XdmcpWriteCARD32(&buf, sessid);
+ XdmcpWriteARRAY8(&buf, &status);
+ XdmcpFlush(xdmcpfd, &buf, clnt_sa, sizeof(struct sockaddr_in));
+}
+
+
+static void
+gdm_xdmcp_handle_keepalive(struct sockaddr_in *clnt_sa, gint len)
+{
+ CARD16 clnt_dspnum;
+ CARD32 clnt_sessid;
+
+ gdm_debug("gdm_xdmcp_handle_keepalive: Got KEEPALIVE from %s",
+ inet_ntoa(clnt_sa->sin_addr));
+
+ /* Check with tcp_wrappers if client is allowed to access */
+ if(!gdm_xdmcp_host_allow(clnt_sa)) {
+ gdm_error(_("gdm_xdmcp_handle_keepalive: Got KEEPALIVE from banned host %s"),
+ inet_ntoa(clnt_sa->sin_addr));
+ return;
+ }
+
+ /* Remote display number */
+ if(!XdmcpReadCARD16(&buf, &clnt_dspnum)) {
+ gdm_error(_("gdm_xdmcp_handle_keepalive: Could not read Display Number"));
+ return;
+ }
+
+ /* SessionID */
+ if(!XdmcpReadCARD32(&buf, &clnt_sessid)) {
+ gdm_error(_("gdm_xdmcp_handle_keepalive: Could not read Session ID"));
+ return;
+ }
+
+ gdm_xdmcp_send_alive(clnt_sa, clnt_sessid);
+}
+
+
+static void
+gdm_xdmcp_send_alive(struct sockaddr_in *clnt_sa, CARD32 sessid)
+{
+ XdmcpHeader header;
+
+ gdm_debug("Sending ALIVE to %d", sessid);
+
+ header.version=XDM_PROTOCOL_VERSION;
+ header.opcode=(CARD16) ALIVE;
+ header.length=5;
+
+ XdmcpWriteHeader(&buf, &header);
+ XdmcpWriteCARD8 (&buf, 1);
+ XdmcpWriteCARD32(&buf, sessid);
+ XdmcpFlush(xdmcpfd, &buf, clnt_sa, sizeof(struct sockaddr_in));
+}
+
+
+static gboolean
+gdm_xdmcp_host_allow(struct sockaddr_in *clnt_sa)
+{
+#ifdef HAVE_TCPWRAPPERS
+ struct hostent *client_he;
+ gchar *client;
+
+ /* Find client hostname */
+ client_he=gethostbyaddr((gchar *) &clnt_sa->sin_addr,
+ sizeof(struct in_addr),
+ AF_INET);
+
+ client=(client_he && client_he->h_name) ? client_he->h_name : NULL;
+
+ /* Check with tcp_wrappers if client is allowed to access */
+ return(hosts_ctl("gdm", client ? client : "unknown", inet_ntoa(clnt_sa->sin_addr), ""));
+#else
+ return(TRUE);
+#endif
+}
+
+
+static GdmDisplay *
+gdm_xdmcp_display_alloc (struct sockaddr_in *clnt_sa, gint displaynum)
+{
+ GdmDisplay *d;
+ struct hostent *client_he;
+
+ d = g_malloc(sizeof(GdmDisplay));
+ d->auth = NULL;
+ d->command = NULL;
+ d->greetpid = 0;
+ d->id = 0;
+ d->servpid = 0;
+ d->servstat = 0;
+ d->sessionid = 0;
+ d->sesspid = 0;
+ d->slavepid = 0;
+ d->type = DISPLAY_XDMCP;
+ d->dispstat = XDMCP_PENDING;
+ d->sessionid = globsessid++;
+ d->acctime = time(NULL);
+ d->dispnum = displaynum;
+
+ /* Find client hostname */
+ client_he=gethostbyaddr((gchar *) &clnt_sa->sin_addr,
+ sizeof(struct in_addr),
+ AF_INET);
+
+ if(client_he) {
+ d->name=g_strdup_printf("%s:%d", client_he->h_name,
+ displaynum);
+ }
+ else
+ d->name=g_strdup_printf("%s:%d", inet_ntoa(clnt_sa->sin_addr),
+ displaynum);
+
+ /* Check if we are already talking to this host */
+ gdm_xdmcp_display_dispose_check(d->name);
+
+ /* Secure display with cookie */
+ gdm_auth_secure_display(d);
+
+ displays=g_slist_append(displays, d);
+
+ pending++;
+
+ gdm_debug("gdm_xdmcp_display_alloc: display=%s, session id=%d, pending=%d ",
+ d->name, d->sessionid, pending);
+
+ return(d);
+}
+
+
+static GdmDisplay *
+gdm_xdmcp_display_lookup(CARD32 sessid)
+{
+ GSList *dlist=displays;
+ GdmDisplay *d;
+
+ while(dlist) {
+ d=(GdmDisplay *)dlist->data;
+
+ if(d && d->sessionid == sessid)
+ return(d);
+
+ dlist=dlist->next;
+ }
+
+ return(NULL);
+}
+
+
+static void
+gdm_xdmcp_display_dispose_check(gchar *name)
+{
+ GSList *dlist=displays;
+ GdmDisplay *d;
+
+ gdm_debug("gdm_xdmcp_display_dispose_check(%s)", name);
+
+ while(dlist) {
+ d=(GdmDisplay *)dlist->data;
+
+ if(d && !strcmp(d->name, name))
+ gdm_display_dispose(d);
+
+ dlist=dlist->next;
+ }
+}
+
+
+static void
+gdm_xdmcp_displays_check(void)
+{
+ GSList *dlist=displays;
+ GdmDisplay *d;
+
+ while(dlist) {
+ d=(GdmDisplay *)dlist->data;
+
+ if(d &&
+ d->type==DISPLAY_XDMCP &&
+ d->dispstat==XDMCP_PENDING &&
+ time(NULL) > d->acctime + GdmMaxManageWait)
+ {
+ gdm_debug("gdm_xdmcp_displays_check: Disposing session id %d",
+ d->sessionid);
+ gdm_display_dispose(d);
+ pending--;
+ }
+
+ dlist=dlist->next;
+ }
+}
+
+
+/* EOF */
diff --git a/docs/Makefile.am b/docs/Makefile.am
new file mode 100644
index 00000000..35720621
--- /dev/null
+++ b/docs/Makefile.am
@@ -0,0 +1,8 @@
+TEXT_FILES = \
+ gdm-manual.txt
+
+docdir = $(prefix)/doc
+doc_DATA = $(TEXT_FILES)
+
+EXTRA_DIST = $(TEXT_FILES)
+
diff --git a/docs/Makefile.in b/docs/Makefile.in
new file mode 100644
index 00000000..61a42584
--- /dev/null
+++ b/docs/Makefile.in
@@ -0,0 +1,255 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AS = @AS@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+GENCAT = @GENCAT@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNOMEGNORBA_LIBS = @GNOMEGNORBA_LIBS@
+GNOMEUI_LIBS = @GNOMEUI_LIBS@
+GNOME_APPLET_LIBS = @GNOME_APPLET_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNOME_INCLUDEDIR = @GNOME_INCLUDEDIR@
+GNOME_LIBDIR = @GNOME_LIBDIR@
+GNOME_LIBS = @GNOME_LIBS@
+GNORBA_CFLAGS = @GNORBA_CFLAGS@
+GNORBA_LIBS = @GNORBA_LIBS@
+GTKXMHTML_LIBS = @GTKXMHTML_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_CONFIG = @GTK_CONFIG@
+GTK_LIBS = @GTK_LIBS@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+NM = @NM@
+ORBIT_CFLAGS = @ORBIT_CFLAGS@
+ORBIT_CONFIG = @ORBIT_CONFIG@
+ORBIT_IDL = @ORBIT_IDL@
+ORBIT_LIBS = @ORBIT_LIBS@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PTHREAD_LIB = @PTHREAD_LIB@
+RANLIB = @RANLIB@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XPM_LIBS = @XPM_LIBS@
+ZVT_LIBS = @ZVT_LIBS@
+ac_xauth = @ac_xauth@
+l = @l@
+
+TEXT_FILES = gdm-manual.txt
+
+
+docdir = $(prefix)/doc
+doc_DATA = $(TEXT_FILES)
+
+EXTRA_DIST = $(TEXT_FILES)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+DATA = $(doc_DATA)
+
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+install-docDATA: $(doc_DATA)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(docdir)
+ @list='$(doc_DATA)'; for p in $$list; do \
+ if test -f $(srcdir)/$$p; then \
+ echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docdir)/$$p"; \
+ $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(docdir)/$$p; \
+ else if test -f $$p; then \
+ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(docdir)/$$p"; \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(docdir)/$$p; \
+ fi; fi; \
+ done
+
+uninstall-docDATA:
+ @$(NORMAL_UNINSTALL)
+ list='$(doc_DATA)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(docdir)/$$p; \
+ done
+tags: TAGS
+TAGS:
+
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = docs
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu docs/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-docDATA
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-docDATA
+uninstall: uninstall-am
+all-am: Makefile $(DATA)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(docdir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-generic distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: uninstall-docDATA install-docDATA tags distdir info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/docs/gdm-manual.txt b/docs/gdm-manual.txt
new file mode 100644
index 00000000..b4b883b1
--- /dev/null
+++ b/docs/gdm-manual.txt
@@ -0,0 +1,352 @@
+
+The Gnome Display Manager
+
+1. Theory of operation
+
+gdm is a replacement for xdm, the X Display Manager. Unlike its
+competitors (x3dm, kdm, wdm) gdm was written from scratch and does not
+contain any original xdm code.
+
+gdm was written with simplicity and security in mind. The overall
+design concept is this:
+
+When gdm starts it parses the config file gdm.conf. For each of the
+local displays gdm forks a slave process. The main gdm process will
+listen to XDMCP requests from remote displays and monitor the local
+display sessions.
+
+The gdm slave process starts an Xserver according to information read
+from the config file. gdm sets up proper X authentication and starts
+up the greeter window requesting the user for login and password.
+
+The gdm master and slave processes are deliberately kept small and
+they are believed to be secure. The program providing the user
+interface is significantly more complex and is linked to several
+unaudited libraries. Therefore it runs as a dedicated gdm user and
+communicates with gdm through a pipe.
+
+
+2. Overview of the config directory.
+
+The configuration files for gdm are located in the <prefix>/etc/gdm/
+directory.
+
+This is a listing of the config directory contents:
+
+ Init/
+ PostSession/
+ PreSession/
+ Sessions/
+ gdm.conf
+
+gdm.conf is the main gdm configuration file. The options will be
+described later in this document.
+
+The remaining configuration is done by dropping scripts in the
+subdirectories of the gdm folder. This approach makes it easy for
+package management systems to install window managers and different
+session types without requiring the sysadmin/user to edit files.
+
+In this section we will explain the Init, PreRoot and PostRoot
+directories as they are very similar.
+
+When the X server has been successfully started, gdm will try to run
+the script called Init/<displayname>. I.e. Init/:0 for the first local
+display. If this file is not found, gdm will attempt to to run
+Init/Default. The script will be run as root and gdm blocks until it
+terminates. Use the Init/* script for programs that are supposed to
+run alongside with the gdm login window. xconsole for
+instance. Commands to set the background etc. goes in this file too.
+
+It is up to the sysadmin to decide whether clients started by the Init
+script should be killed before starting the user session. This is
+controlled with the KillInitClient option in gdm.conf.
+
+When the user has been successfully authenticated, gdm tries to run
+the PreSession script. Similar to the Init-scripts,
+PreSession/<displayname> will be executed first, if that is not found
+gdm will attempt to run PreSession/Default. The script will be run as
+root and gdm blocks until it terminates. Use this script for local
+session management or accounting stuff. The USER environment variable
+contains the login of the authenticated user. The script should return
+0 on success. Any other value will cause gdm to terminate the current
+login process.
+
+Then the session script is run. Session scripts are located in the
+etc/gdm/Session directory. Which one gdm runs depends on the session
+the user chose in the Sessions-menu in the gdm greeter. If no session
+is selected and the user has no last session stored in his
+~/.gnome/gdm file, the system will choose or first script found or --
+if Sessions/Default exists -- this will be run. For instance you can
+create a symlink from Gnome to Default to make Gnome the default
+desktop environment.
+
+When the user terminates his session the PostSession script will be
+run. Operation is similar to Init and PreSession. That is, gdm will
+attempt to execute the script PostSession/<displayname> and if that
+doesn't exist: PostSession/Default. Again the script will be run with
+root priviledges, gdm will block and the USER environment variable
+will contain the name of the user who just logged out.
+
+Neither of the Init, PreSession or PostSession scripts are necessary
+and can be left out. At least one session script is required for
+proper operation.
+
+
+3. The Login Window
+
+gdm supports two different login modes (which happen to be selected
+by changing greeter programs).
+
+
+The gdmlogin program is a bare bones gui application providing only a
+few menus and a login prompt. A graphical version of the textmode
+login program, if you wish.
+
+gdmlogin was designed for use in environments, where usernames can't
+be exposed.
+
+
+gdmgreeter is slightly more powerful. It consists of a browser window
+containing faces of all users on the system.
+
+~user/.gnome/photo is expected to contain an Imlib supported
+image. gdmgreeter will scale down large images to the sysadmin
+specified maximum.
+
+
+4. The config file
+
+
+4.1 Section: [appearance]
+
+LogoImage=@pixmapdir@/gnome-logo-large.png
+ Filename to display in the logo box. The image must be in an
+ Imlib supported format and it must be readable for the gdm
+ user.
+
+Quiver=1
+ Controls whether gdmgreeter should shake the display when an
+ incorrect username/password is entered. Default: 1.
+
+Iconify=1
+ The greeter window can be iconified (For TV and fish). You can
+ turn the iconify option off by setting this to 0. Default: 1.
+
+IconFile=@pixmapdir@/gdm.xpm
+ File to use for gdmgreeter when it's in iconified state. The
+ image must be in an Imlib supported format and it must be
+ readable for the gdm user.
+
+Gtkrc=
+ Path to a gtkrc containing the theme for use in
+ gdmgreeter/gdmlogin/gdmchooser.
+
+NoFaceImage=@pixmapdir@/nophoto.png
+ (Only used by gdmgreeter)
+
+ Default icon file for users without a personal picture in
+ ~/gnome/photo. The image must be in an Imlib supported format
+ and it must be readable for the gdm user.
+
+GlobalImageDir=@datadir@/faces/
+ (Only used by gdmgreeter)
+
+ Systemwide directory for icon files. The sysadmin can place
+ icons for users here without touching their homedirs. The
+ iconname represents a user name. I.e. GlobalImageDir/johndoe
+ would contain the icon for the user johndoe (No
+ extension!). The images must be in an Imlib supported format
+ and they must be readable for the gdm user.
+
+ A user's own icon file will take precedence over the sysadmin
+ provided one.
+
+
+4.2 Section: [system]
+
+ShutdownMenu=0
+ Turns the Shutdown/Halt menu on/off. Default: 0
+
+SuspendCommand=
+ If specified a Suspend item will appear in the System menu in
+ gdmgreeter. The command specified here will be executed
+ asynchronously. Please use full path!
+
+ For instance
+
+ SuspendCommand=/usr/bin/apm --suspend
+
+UserFileCutoffSize=65535
+ User files larger than this value (in bytes) will be ignored
+ by gdm/gdmgreeter. Handy for users putting gigantic pictures
+ in their ~/.gnome/photo.
+
+ In addition to the size check both gdm and gdmgreeter are
+ extremely picky about accessing files in user directories.
+ Neither will follow symlinks and they refuse to read files and
+ directories writable by other than the owner.
+
+UserIconMaxWidth=128
+UserIconMaxHeight=128
+ Specifies the maximum icon sizes in the face browser.
+
+DefaultPath=@bindir@:/usr/local/bin:/usr/bin/X11:/usr/bin:/bin
+ Specifies the path which will be set in the user's session.
+
+VerboseAuth=0
+ Specifies whether gdm should print authentication
+ errors. Depending on authentication type usernames might be
+ exposed when this option is on.
+
+AllowRoot=0
+ Set to 1 to enable root logins.
+
+RelaxPermissions=0
+ By default gdm ignores files/dirs writable to other users than
+ the owner.
+
+ Changing the value of RelaxPermissions makes it possible to
+ alter this behaviour:
+
+ 0 - Paranoia option. Only accepts user owned files and dirs.
+ 1 - Allow group writable files/dirs
+ 2 - Allow world writable files/dirs
+
+RetryDelay=3
+ The number of seconds gdm should wait before reactivating the
+ entry field after a failed login.
+
+
+4.3 Section: [messages]
+
+Welcome=Welcome to %h
+ Controls which text to display next to the logo image in the
+ greeter.
+
+ `%h' will be expanded to the hostname
+ `%d' will be replaced by the display's hostname
+ `%%' will print the %-character
+
+
+4.4 Section: [daemon]
+
+SessionDir=@sysconfdir@/gdm/Sessions
+ Directory containing the Session scripts.
+
+PidFile=/var/run/gdm.pid
+ Name of the gdm daemon pidfile.
+
+Greeter=@bindir@/gdmgreeter
+ Path and name of the login program executable.
+
+ @bindir@/gdmlogin for the secure login window.
+
+ @bindir@/gdmgreeter for the face browser.
+
+Chooser=@bindir@/gdmchooser
+ Path and name of the gdmchooser executable.
+
+User=gdm
+ The username under which gdm is run.
+
+Group=gdm
+ The group id under which gdmgreeter is run.
+
+DisplayInitDir=@sysconfdir@/gdm/Init
+ Directory containing the Init scripts.
+
+KillInitClients=1
+ Determines whether gdm should kill X clients started by the
+ Init scripts when the user logs in. Default: 1.
+
+PreSessionScriptDir=@sysconfdir@/gdm/PreSession
+ Directory containing the PreSession scripts.
+
+PostSessionScriptDir=@sysconfdir@/gdm/PostSession
+ Directory containing the PostSession scripts.
+
+AuthDir=@authdir@
+ Directory containing the X authentication files for the
+ displays. Should be owned by gdm.gdm with permissions 750.
+
+LogDir=@authdir@
+ Directory containing the log files for the displays. By
+ default this is the same as the AuthDir.
+
+
+4.5 Section: [servers]
+
+0=/usr/bin/X11/X
+1=/usr/bin/X11/X -bpp 8
+
+ Control section for local X servers. Each line indicates the
+ local display number and which command needs to be run to
+ start the X server(s).
+
+
+4.6 Section: [xdmcp]
+
+Enable=1
+ Enables XDMCP support allowing remote displays/X terminals to
+ be managed by gdm.
+
+ gdm listens for requests on UDP port 177. Access from remote
+ displays is controlled by the TCP Wrappers library. The
+ service name is `gdm'.
+
+ You should add
+
+ gdm: .my.domain
+
+ or something similar to /etc/hosts.allow. See the
+ hosts_access(5) man page for details.
+
+ Please note that XDMCP is not a particularly secure protocol
+ and that it is a good idea to block UDP port 177 on your
+ firewall unless you really need it.
+
+MaxPending=4
+ To avoid denial of service attacks, gdm has fixed size queue
+ of pending connections. Only MaxPending displays can start at
+ the same time.
+
+ Please note that this parameter does *not* limit the number of
+ remote displays which can be managed. It only limits the
+ number of simultaneous displays initiating a connection.
+
+MaxManageWait=20
+ When gdm is ready to manage a display an ACCEPT packet is sent
+ to it containing a unique session id which will be used in
+ future conversations.
+
+ gdm will then place the session id in the pending queue
+ waiting for the display to respond with a MANAGE request.
+
+ If no response is received within MaxManageWait seconds, gdm
+ will declare the display dead and erase it from the pending
+ queue freeing up the slot for other displays.
+
+MaxSessions=4
+ Determines the maximum number of remote display connections
+ which will be accepted.
+
+Port=177
+ The UDP port number gdm should listen to for XDMCP requests.
+
+
+4.7 Section: [chooser]
+
+ImageDir=@datadir@/hosts
+ Repository for host icon files. The sysadmin can place icons
+ for remote hosts here and they will appear in gdmchooser.
+
+ The file name must match the FQDN for the host (No extension!).
+ Icons must be in an Imlib supported format and must be
+ readable to the gdm user.
+
+DefaultImage=@pixmapdir@/nohost.png
+ File name for the default host icon.
+
+
+$Id$
diff --git a/gdm.spec b/gdm.spec
new file mode 100644
index 00000000..77ad68a3
--- /dev/null
+++ b/gdm.spec
@@ -0,0 +1,78 @@
+# Note that this is NOT a relocatable package
+%define ver 1.0.1
+%define rel 1
+%define prefix /usr
+
+Summary: GNOME Display Manager
+Name: gdm
+Version: %ver
+Release: %rel
+Copyright: GPL
+Group: User Interface/X
+Source: ftp://ftp.gnome.org/sources/gdm/gdm-%{ver}.tar.gz
+
+BuildRoot: /var/tmp/gdm-%{PACKAGE_VERSION}-root
+Docdir: %{prefix}/doc
+Requires: gnome-libs >= 1.0.0
+
+%description
+GNOME Display Manager allows you to log into your system with the
+X Window System running. It is highly configurable, allowing you
+to run several different X sessions at once on your local machine,
+and can manage login connections from remote machines as well.
+
+%changelog
+
+%prep
+%setup
+
+%build
+libtoolize --copy --force
+CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%prefix --sysconfdir=/etc --localstatedir=/var
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+/usr/sbin/useradd -u 42 -r gdm > /dev/null 2>&1 || /bin/true
+
+make prefix=$RPM_BUILD_ROOT%{prefix} sysconfdir=$RPM_BUILD_ROOT/etc localstatedir=$RPM_BUILD_ROOT/var install
+# docs go elsewhere
+rm -rf $RPM_BUILD_ROOT/%{prefix}/doc
+
+%clean
+[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf $RPM_BUILD_ROOT
+
+%pre
+/usr/sbin/useradd -u 42 -r gdm > /dev/null 2>&1
+# ignore errors, as we can't disambiguate between gdm already existed
+# and couldn't create account with the current adduser.
+exit 0
+
+%files
+%defattr(-, root, root)
+
+%doc AUTHORS COPYING ChangeLog NEWS README README.install docs/gdm-manual.txt
+%{prefix}/bin/*
+%config /etc/pam.d/gdm
+%config /etc/gnomerc
+%config /etc/gdm/gdm.conf
+%config /etc/gdm/Sessions/*
+%{prefix}/share/locale/*/*/*
+%{prefix}/share/pixmaps/*
+%attr(750, gdm, gdm) %dir /var/gdm
+
+%changelog
+* Thu Mar 4 1999 Martin K. Petersen <mkp@mkp.net>
+- misc. fixes. Red Hatters: I removed your gdm.conf/Xsession patch
+ from this spec file. Stuff it back in for your own builds.
+
+* Thu Feb 25 1999 Michael Fulbright <drmike@redhat.com>
+- moved files from /usr/etc to /etc
+
+* Tue Feb 16 1999 Michael Johnson <johnsonm@redhat.com>
+- removed commented-out #1 definition -- put back after testing gnome-libs
+ comment patch
+
+* Sat Feb 06 1999 Michael Johnson <johnsonm@redhat.com>
+- initial packaging
diff --git a/gui/Makefile.am b/gui/Makefile.am
new file mode 100644
index 00000000..fffcd01f
--- /dev/null
+++ b/gui/Makefile.am
@@ -0,0 +1,25 @@
+## Process this file with automake to produce makefile.in
+CFLAGS += -g -Wall \
+ -Wpointer-arith \
+ -Wmissing-prototypes -Wmissing-declarations
+
+DEFS += -DGDM_CONFIG_FILE=\"@sysconfdir@/gdm/gdm.conf\"
+
+INCLUDES = -I. -I.. -I$(top_srcdir)/daemon -I$(includedir) \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ -DLOCALEDIR=\"$(datadir)/locale\" \
+ $(GNOME_INCLUDEDIR)
+
+bin_PROGRAMS = gdmchooser gdmlogin
+
+gdmchooser_SOURCES = \
+ gdmchooser.c \
+ gdmchooser.h
+
+gdmlogin_SOURCES = \
+ gdmlogin.c \
+ filecheck.c
+
+gdmchooser_LDADD = $(GNOME_LIBDIR) $(GNOME_LIBS) $(GNOMEUI_LIBS) -lXdmcp -lX11 $(INTLLIBS)
+gdmlogin_LDADD = $(GNOME_LIBDIR) $(GNOME_LIBS) $(GNOMEUI_LIBS) $(INTLLIBS)
+
diff --git a/gui/Makefile.in b/gui/Makefile.in
new file mode 100644
index 00000000..f09d6c95
--- /dev/null
+++ b/gui/Makefile.in
@@ -0,0 +1,400 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AS = @AS@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CPPFLAGS = @CPPFLAGS@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+GENCAT = @GENCAT@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNOMEGNORBA_LIBS = @GNOMEGNORBA_LIBS@
+GNOMEUI_LIBS = @GNOMEUI_LIBS@
+GNOME_APPLET_LIBS = @GNOME_APPLET_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNOME_INCLUDEDIR = @GNOME_INCLUDEDIR@
+GNOME_LIBDIR = @GNOME_LIBDIR@
+GNOME_LIBS = @GNOME_LIBS@
+GNORBA_CFLAGS = @GNORBA_CFLAGS@
+GNORBA_LIBS = @GNORBA_LIBS@
+GTKXMHTML_LIBS = @GTKXMHTML_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_CONFIG = @GTK_CONFIG@
+GTK_LIBS = @GTK_LIBS@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+NM = @NM@
+ORBIT_CFLAGS = @ORBIT_CFLAGS@
+ORBIT_CONFIG = @ORBIT_CONFIG@
+ORBIT_IDL = @ORBIT_IDL@
+ORBIT_LIBS = @ORBIT_LIBS@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PTHREAD_LIB = @PTHREAD_LIB@
+RANLIB = @RANLIB@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XPM_LIBS = @XPM_LIBS@
+ZVT_LIBS = @ZVT_LIBS@
+ac_xauth = @ac_xauth@
+l = @l@
+
+CFLAGS = @CFLAGS@ -g -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations
+
+
+DEFS = -DGDM_CONFIG_FILE=\"@sysconfdir@/gdm/gdm.conf\"
+
+INCLUDES = -I. -I.. -I$(top_srcdir)/daemon -I$(includedir) -DGNOMELOCALEDIR=\""$(datadir)/locale"\" -DLOCALEDIR=\"$(datadir)/locale\" $(GNOME_INCLUDEDIR)
+
+
+bin_PROGRAMS = gdmchooser gdmlogin
+
+gdmchooser_SOURCES = gdmchooser.c gdmchooser.h
+
+
+gdmlogin_SOURCES = gdmlogin.c filecheck.c
+
+
+gdmchooser_LDADD = $(GNOME_LIBDIR) $(GNOME_LIBS) $(GNOMEUI_LIBS) -lXdmcp -lX11 $(INTLLIBS)
+gdmlogin_LDADD = $(GNOME_LIBDIR) $(GNOME_LIBS) $(GNOMEUI_LIBS) $(INTLLIBS)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(bin_PROGRAMS)
+
+LIBS = @LIBS@
+gdmchooser_OBJECTS = gdmchooser.o
+gdmchooser_DEPENDENCIES =
+gdmchooser_LDFLAGS =
+gdmlogin_OBJECTS = gdmlogin.o filecheck.o
+gdmlogin_DEPENDENCIES =
+gdmlogin_LDFLAGS =
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = gtar
+GZIP_ENV = --best
+DEP_FILES = .deps/filecheck.P .deps/gdmchooser.P .deps/gdmlogin.P
+SOURCES = $(gdmchooser_SOURCES) $(gdmlogin_SOURCES)
+OBJECTS = $(gdmchooser_OBJECTS) $(gdmlogin_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu gui/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+gdmchooser: $(gdmchooser_OBJECTS) $(gdmchooser_DEPENDENCIES)
+ @rm -f gdmchooser
+ $(LINK) $(gdmchooser_LDFLAGS) $(gdmchooser_OBJECTS) $(gdmchooser_LDADD) $(LIBS)
+
+gdmlogin: $(gdmlogin_OBJECTS) $(gdmlogin_DEPENDENCIES)
+ @rm -f gdmlogin
+ $(LINK) $(gdmlogin_LDFLAGS) $(gdmlogin_OBJECTS) $(gdmlogin_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = gui
+
+distdir: $(DISTFILES)
+ here=`cd $(top_builddir) && pwd`; \
+ top_distdir=`cd $(top_distdir) && pwd`; \
+ distdir=`cd $(distdir) && pwd`; \
+ cd $(top_srcdir) \
+ && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu gui/Makefile
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+ -rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+ @echo '$(COMPILE) -c $<'; \
+ $(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-cp .deps/$(*F).pp .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm .deps/$(*F).pp
+
+%.lo: %.c
+ @echo '$(LTCOMPILE) -c $<'; \
+ $(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+ @-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
+ < .deps/$(*F).pp > .deps/$(*F).P; \
+ tr ' ' '\012' < .deps/$(*F).pp \
+ | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+ >> .deps/$(*F).P; \
+ rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+ clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-binPROGRAMS distclean-compile distclean-libtool \
+ distclean-tags distclean-depend distclean-generic \
+ clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-binPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-tags maintainer-clean-depend \
+ maintainer-clean-generic distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir \
+mostlyclean-depend distclean-depend clean-depend \
+maintainer-clean-depend info-am info dvi-am dvi check check-am \
+installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gui/gdmchooser.c b/gui/gdmchooser.c
new file mode 100644
index 00000000..7cdf970b
--- /dev/null
+++ b/gui/gdmchooser.c
@@ -0,0 +1,676 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#include <X11/Xdmcp.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
+#include "gdmchooser.h"
+
+static const gchar RCSid[]="$Id$";
+
+static void gdm_chooser_decode_packet(void);
+static GdmChooserHost *gdm_chooser_host_alloc (gchar *hostname, gchar *description);
+static void gdm_chooser_abort(const gchar *format, ...);
+static void gdm_chooser_browser_update(void);
+static void gdm_chooser_xdmcp_init(void);
+static void gdm_chooser_host_dispose(GdmChooserHost *host);
+
+int XdmcpReallocARRAY8 (ARRAY8Ptr array, int length);
+
+
+typedef struct _XdmAuth {
+ ARRAY8 authentication;
+ ARRAY8 authorization;
+} XdmAuthRec, *XdmAuthPtr;
+
+static XdmAuthRec authlist = {
+ { (CARD16) 0, (CARD8 *) 0 },
+ { (CARD16) 0, (CARD8 *) 0 }
+};
+
+
+gint sockfd;
+static XdmcpBuffer querybuf;
+GSList *bcaddr;
+
+gint GdmIconMaxHeight;
+gint GdmIconMaxWidth;
+gint GdmDebug;
+gint GdmRescanTime;
+gint GdmDeadTime;
+gchar *GdmHostIconDir;
+gchar *GdmHostDefaultIcon;
+gchar *GdmGtkRC;
+
+GtkWidget *chooser;
+GtkWidget *manage;
+GtkWidget *rescan;
+GtkWidget *cancel;
+
+gint maxwidth=0;
+guint tid;
+GIOChannel *channel;
+
+GList *hosts=NULL;
+GdkImlibImage *nohostimg;
+GnomeIconList *browser;
+
+GdmChooserHost *curhost;
+
+
+static gint
+gdm_chooser_sort_func(gpointer d1, gpointer d2)
+{
+ GdmChooserHost *a=d1;
+ GdmChooserHost *b=d2;
+
+ return strcmp(a->name, b->name);
+}
+
+
+static void
+gdm_chooser_decode_packet(void)
+{
+ struct sockaddr_in clnt_sa;
+ gint sa_len=sizeof(clnt_sa);
+ static XdmcpBuffer buf;
+ XdmcpHeader header;
+ struct hostent *he;
+ gchar *hostname, *status=NULL;
+ ARRAY8 auth, host, stat;
+
+ if(!XdmcpFill(sockfd, &buf, &clnt_sa, &sa_len))
+ return;
+
+ if(!XdmcpReadHeader(&buf, &header))
+ return;
+
+ if(header.version != XDM_PROTOCOL_VERSION)
+ return;
+
+ 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(stat.data, stat.length);
+
+ he=gethostbyaddr((gchar *) &clnt_sa.sin_addr,
+ sizeof(struct in_addr),
+ AF_INET);
+
+ hostname=(he && he->h_name) ? he->h_name : inet_ntoa(clnt_sa.sin_addr);
+
+ hosts=g_list_insert_sorted(hosts,
+ gdm_chooser_host_alloc(hostname, (gchar *) status),
+ (GCompareFunc) gdm_chooser_sort_func);
+
+ done:
+ XdmcpDisposeARRAY8(&auth);
+ XdmcpDisposeARRAY8(&host);
+ XdmcpDisposeARRAY8(&stat);
+
+ g_free(status);
+
+ return;
+ }
+
+}
+
+
+/* Find broadcast address for all active, non pointopoint interfaces */
+static void
+gdm_chooser_find_bcaddr(void)
+{
+ gint i=0;
+ struct ifconf ifcfg;
+ struct ifreq ifr[MAXIF];
+ struct in_addr *ia;
+
+ ifcfg.ifc_buf=(gchar *)&ifr;
+ ifcfg.ifc_len=sizeof(ifr);
+
+ memset(ifr, 0, sizeof(ifr));
+
+ if(ioctl(sockfd, SIOCGIFCONF, &ifcfg) < 0)
+ gdm_chooser_abort("Could not get SIOCIFCONF");
+
+ for(i=0 ; i < MAXIF ; i++)
+ if(strlen(ifr[i].ifr_name)) {
+ struct ifreq *ifreq;
+ struct sockaddr_in *ba;
+
+ ifreq=g_new0(struct ifreq, 1);
+
+ strncpy(ifreq->ifr_name, ifr[i].ifr_name, sizeof(ifr[i].ifr_name));
+
+ if(ioctl(sockfd, SIOCGIFFLAGS, ifreq) < 0)
+ gdm_chooser_abort("Could not get SIOCGIFFLAGS for %s", ifr[i].ifr_name);
+
+ if((ifreq->ifr_flags & IFF_UP) == 0)
+ goto done;
+
+ if((ifreq->ifr_flags & IFF_BROADCAST) == 0)
+ goto done;
+
+ if(ioctl(sockfd, SIOCGIFBRDADDR, ifreq) < 0) {
+ goto done;
+ }
+
+ ba=(struct sockaddr_in *)&ifreq->ifr_broadaddr;
+
+ ia=g_new0(struct in_addr, 1);
+
+ ia->s_addr = ba->sin_addr.s_addr;
+
+ bcaddr=g_slist_append(bcaddr, ia);
+
+ done:
+ g_free(ifreq);
+ }
+}
+
+
+static gboolean
+gdm_chooser_xdmcp_discover(void)
+{
+ struct sockaddr_in sock;
+ GSList *bl=bcaddr;
+ struct in_addr *ia;
+ GList *hl=hosts;
+
+ gtk_widget_set_sensitive (chooser, FALSE);
+ gnome_icon_list_freeze(browser);
+ gnome_icon_list_clear(browser);
+
+ while(hl) {
+ gdm_chooser_host_dispose((GdmChooserHost *) hl->data);
+ hl=hl->next;
+ }
+
+ g_list_free(hosts);
+
+ hosts=NULL;
+
+ sock.sin_family = AF_INET;
+ sock.sin_port = htons (XDM_UDP_PORT);
+
+ while(bl) {
+ ia = (struct in_addr *)bl->data;
+
+ sock.sin_addr.s_addr = ia->s_addr;
+ XdmcpFlush (sockfd, &querybuf, &sock, sizeof(struct sockaddr_in));
+ bl=bl->next;
+ }
+
+ tid=g_timeout_add(GdmRescanTime*1000,
+ (GSourceFunc) gdm_chooser_browser_update, NULL);
+
+ return(TRUE);
+}
+
+
+static void
+gdm_chooser_xdmcp_init(void)
+{
+ static XdmcpHeader header;
+ gint sockopts=1;
+
+ /* Open socket for communication */
+ if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ gdm_chooser_abort("Could not create socket()!");
+
+ if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char *)&sockopts, sizeof (sockopts)) < 0)
+ gdm_chooser_abort("Could not set socket options!");
+
+ gdm_chooser_find_bcaddr();
+
+ /* Assemble XDMCP BROADCAST_QUERY packet in static buffer */
+ header.opcode = (CARD16) BROADCAST_QUERY;
+ header.length = 1;
+ header.version = XDM_PROTOCOL_VERSION;
+ XdmcpWriteHeader(&querybuf, &header);
+ XdmcpWriteARRAY8(&querybuf, &authlist.authentication);
+
+ channel = g_io_channel_unix_new(sockfd);
+ g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
+ G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ (GIOFunc) gdm_chooser_decode_packet,
+ GINT_TO_POINTER(sockfd), NULL);
+ g_io_channel_unref(channel);
+
+ gdm_chooser_xdmcp_discover();
+}
+
+
+static gboolean
+gdm_chooser_cancel(void)
+{
+ closelog();
+ gtk_main_quit();
+
+ return(TRUE);
+}
+
+
+static gboolean
+gdm_chooser_manage(void)
+{
+ if(curhost)
+ g_print("%s\n", curhost->name);
+
+ closelog();
+ gtk_main_quit();
+
+ return(TRUE);
+}
+
+
+static void
+gdm_chooser_abort(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_ERR, s);
+
+ closelog();
+ exit(EXIT_FAILURE);
+}
+
+
+static void
+gdm_chooser_parse_config(void)
+{
+ struct stat unused;
+
+ if(stat(GDM_CONFIG_FILE, &unused) == -1)
+ gdm_chooser_abort(_("gdm_chooser_parse_config: No configuration file: %s. Aborting."), GDM_CONFIG_FILE);
+
+ gnome_config_push_prefix ("=" GDM_CONFIG_FILE "=/");
+
+ GdmGtkRC=gnome_config_get_string("appearance/gtkrc");
+
+ GdmRescanTime=gnome_config_get_int("chooser/rescantime=3");
+ GdmDeadTime=gnome_config_get_int("chooser/deadtime=3");
+ GdmHostDefaultIcon=gnome_config_get_string("chooser/defaultimage=nohost.xpm");
+ GdmHostIconDir=gnome_config_get_string("chooser/imagedir");
+
+ GdmIconMaxWidth=gnome_config_get_int("system/UserIconMaxWidth=128");
+ GdmIconMaxHeight=gnome_config_get_int("system/UserIconMaxHeight=128");
+
+ GdmDebug=gnome_config_get_int("debug/enable=0");
+
+ gnome_config_pop_prefix ();
+}
+
+
+static gboolean
+gdm_chooser_browser_select(GtkWidget *widget, gint selected, GdkEvent *event)
+{
+ if(!event)
+ return(TRUE);
+ else
+ switch(event->type) {
+
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ curhost=g_list_nth_data(hosts, selected);
+ gtk_widget_set_sensitive (manage, TRUE);
+ break;
+
+ default:
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+static gboolean
+gdm_chooser_browser_unselect(GtkWidget *widget, gint selected, GdkEvent *event)
+{
+ if(event) {
+ switch(event->type) {
+
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ curhost=NULL;
+ gtk_widget_set_sensitive (manage, FALSE);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return(TRUE);
+}
+
+
+static void
+gdm_chooser_browser_update(void)
+{
+ GList *list=hosts;
+
+ g_source_remove(tid);
+
+ while(list) {
+ GdmChooserHost *host;
+ gchar *temp;
+
+ host=(GdmChooserHost *)list->data;
+
+ temp=g_strconcat(host->name, "\n", host->desc, NULL);
+ gnome_icon_list_append_imlib(browser, host->picture, temp);
+ g_free(temp);
+
+ list=list->next;
+ }
+
+ gnome_icon_list_thaw(browser);
+
+ gtk_widget_set_sensitive(chooser, TRUE);
+ gtk_widget_set_sensitive(manage, FALSE);
+ gtk_widget_show_all(chooser);
+}
+
+
+static void
+gdm_chooser_gui_init (void)
+{
+ GdkWindow *rootwin;
+ GtkWidget *frame;
+ GtkWidget *vbox;
+ GtkWidget *bbox;
+ GtkWidget *buttonpane;
+ GtkWidget *scrollbar;
+ GtkWidget *bframe;
+ GtkStyle *style;
+ GdkColor bbg = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
+ struct stat statbuf;
+
+ /* Enable theme */
+ if(GdmGtkRC)
+ gtk_rc_parse(GdmGtkRC);
+
+ /* Load default host image */
+ if(stat(GdmHostDefaultIcon, &statbuf))
+ gdm_chooser_abort(_("Can't open default host icon: %s"), GdmHostDefaultIcon);
+ else {
+ nohostimg=gdk_imlib_load_image(GdmHostDefaultIcon);
+ maxwidth=nohostimg->rgb_width;
+ }
+
+ /* Root Window */
+ rootwin=gdk_window_foreign_new (GDK_ROOT_WINDOW ());
+
+ /* Main window */
+ chooser = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_container_border_width (GTK_CONTAINER (chooser), 0);
+
+ /* 3D frame for main window */
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME (frame), GTK_SHADOW_OUT);
+ gtk_container_border_width (GTK_CONTAINER (frame), 0);
+ gtk_container_add(GTK_CONTAINER (chooser), frame);
+
+ /* Vertical box containing browser box and button pane */
+ vbox = gtk_vbox_new(FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (vbox), 10);
+ gtk_container_add(GTK_CONTAINER (frame), vbox);
+
+ /* Find background style for browser */
+ style = gtk_style_copy (chooser->style);
+ style->bg[GTK_STATE_NORMAL] = bbg;
+ gtk_widget_push_style(style);
+
+ /* Icon list */
+ if(maxwidth < GdmIconMaxWidth/2)
+ maxwidth=(gint) GdmIconMaxWidth/2;
+
+ browser = GNOME_ICON_LIST (gnome_icon_list_new (maxwidth+20, NULL, FALSE));
+ gnome_icon_list_freeze (GNOME_ICON_LIST (browser));
+ gnome_icon_list_set_separators (browser, " /-_.");
+ gnome_icon_list_set_row_spacing (browser, 2);
+ gnome_icon_list_set_col_spacing (browser, 2);
+ gnome_icon_list_set_icon_border (browser, 2);
+ gnome_icon_list_set_text_spacing (browser, 2);
+ gnome_icon_list_set_selection_mode (browser, GTK_SELECTION_SINGLE);
+ gtk_signal_connect (GTK_OBJECT (browser), "select_icon",
+ GTK_SIGNAL_FUNC (gdm_chooser_browser_select), NULL);
+ gtk_signal_connect (GTK_OBJECT (browser), "unselect_icon",
+ GTK_SIGNAL_FUNC (gdm_chooser_browser_unselect), NULL);
+ gtk_widget_pop_style();
+
+ /* Browser 3D frame */
+ bframe = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME (bframe), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(bframe), GTK_WIDGET(browser));
+
+ /* Browser scroll bar */
+ scrollbar = gtk_vscrollbar_new (browser->adj);
+
+ /* Box containing all browser functionality */
+ bbox = gtk_hbox_new (0, 0);
+ gtk_box_pack_start (GTK_BOX (bbox), GTK_WIDGET (bframe), 1, 1, 0);
+ gtk_box_pack_start (GTK_BOX (bbox), scrollbar, 0, 0, 0);
+ gtk_widget_show_all(GTK_WIDGET(bbox));
+
+ /* Put browser box in main window */
+ gtk_box_pack_start(GTK_BOX (vbox), GTK_WIDGET(bbox), TRUE, TRUE, 0);
+
+ /* Buttons */
+ manage = gtk_button_new_with_label(_("Connect"));
+ gtk_signal_connect(GTK_OBJECT (manage), "clicked",
+ GTK_SIGNAL_FUNC (gdm_chooser_manage), NULL);
+ GTK_WIDGET_SET_FLAGS(manage, GTK_CAN_DEFAULT);
+ gtk_widget_set_sensitive (manage, FALSE);
+ gtk_widget_show(manage);
+
+ rescan = gtk_button_new_with_label(_("Rescan"));
+ gtk_signal_connect(GTK_OBJECT (rescan), "clicked",
+ GTK_SIGNAL_FUNC (gdm_chooser_xdmcp_discover), NULL);
+ GTK_WIDGET_SET_FLAGS(rescan, GTK_CAN_DEFAULT);
+ gtk_widget_show(rescan);
+
+ cancel = gtk_button_new_with_label(_("Cancel"));
+ gtk_signal_connect(GTK_OBJECT (cancel), "clicked",
+ GTK_SIGNAL_FUNC (gdm_chooser_cancel), NULL);
+ GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
+ gtk_widget_show(cancel);
+
+ /* Button pane */
+ buttonpane = gtk_hbox_new(TRUE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER (buttonpane), 0);
+ gtk_box_pack_start(GTK_BOX (buttonpane),
+ manage, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX (buttonpane),
+ rescan, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX (buttonpane),
+ cancel, TRUE, TRUE, 0);
+ gtk_window_set_default(GTK_WINDOW(chooser), GTK_WIDGET(manage));
+ gtk_widget_show_all(buttonpane);
+
+ /* Put button pane in main window */
+ gtk_box_pack_end(GTK_BOX (vbox),
+ buttonpane, FALSE, FALSE, 0);
+
+ gtk_widget_show(vbox);
+ gtk_widget_show(frame);
+
+ gtk_window_set_policy(GTK_WINDOW (chooser), 1, 1, 1);
+ gtk_window_set_focus(GTK_WINDOW (chooser), manage);
+
+ /* Geometry fun */
+ gtk_widget_show_all(GTK_WIDGET(browser));
+ gnome_icon_list_thaw (GNOME_ICON_LIST (browser));
+ gtk_widget_set_usize(GTK_WIDGET (chooser),
+ (gint) gdk_screen_width() * 0.4,
+ (gint) gdk_screen_height() * 0.6);
+
+ gtk_window_position(GTK_WINDOW (chooser), GTK_WIN_POS_CENTER);
+ gtk_widget_show_all(chooser);
+}
+
+
+static void
+gdm_chooser_signals_init(void)
+{
+ struct sigaction hup;
+ sigset_t mask;
+
+ hup.sa_handler = (void *) gdm_chooser_cancel;
+ hup.sa_flags = 0;
+ sigemptyset(&hup.sa_mask);
+
+ if(sigaction(SIGHUP, &hup, NULL) < 0)
+ gdm_chooser_abort(_("main: Error setting up HUP signal handler"));
+
+ if(sigaction(SIGINT, &hup, NULL) < 0)
+ gdm_chooser_abort(_("main: Error setting up INT signal handler"));
+
+ if(sigaction(SIGTERM, &hup, NULL) < 0)
+ gdm_chooser_abort(_("main: Error setting up TERM signal handler"));
+
+ sigfillset(&mask);
+ sigdelset(&mask, SIGTERM);
+ sigdelset(&mask, SIGHUP);
+ sigdelset(&mask, SIGINT);
+
+ if(sigprocmask(SIG_SETMASK, &mask, NULL) == -1) {
+ syslog(LOG_ERR, "Could not set signal mask!");
+ exit(EXIT_FAILURE);
+ }
+}
+
+static GdmChooserHost *
+gdm_chooser_host_alloc (gchar *hostname, gchar *description)
+{
+ GdmChooserHost *host;
+ GdkImlibImage *imlibimg;
+ gint w, h;
+ gchar *hostimg;
+ struct stat statbuf;
+
+ host=g_malloc(sizeof(GdmChooserHost));
+ host->name=g_strdup(hostname);
+ host->desc=g_strdup(description);
+
+ hostimg=g_strconcat(GdmHostIconDir, "/", hostname, NULL);
+
+ if (!stat(hostimg, &statbuf) && (imlibimg=gdk_imlib_load_image(hostimg))) {
+
+ w=imlibimg->rgb_width;
+ h=imlibimg->rgb_height;
+
+ if(w>h && w>GdmIconMaxWidth) {
+ h=h*((gfloat) GdmIconMaxWidth/w);
+ w=GdmIconMaxWidth;
+ }
+ else if(h>GdmIconMaxHeight) {
+ w=w*((gfloat) GdmIconMaxHeight/h);
+ h=GdmIconMaxHeight;
+ }
+
+ maxwidth=MAX(maxwidth, w);
+
+ host->picture=gdk_imlib_clone_scaled_image(imlibimg, w, h);
+
+ gdk_imlib_destroy_image(imlibimg);
+ }
+ else
+ host->picture=nohostimg;
+
+ g_free(hostimg);
+
+ return (host);
+}
+
+
+static void
+gdm_chooser_host_dispose(GdmChooserHost *host)
+{
+ if(!host)
+ return;
+
+ if(host->picture != nohostimg)
+ gdk_imlib_destroy_image(host->picture);
+
+ g_free(host->name);
+ g_free(host->desc);
+ g_free(host);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ /* Avoid creating ~gdm/.gnome stuff */
+ gnome_do_not_create_directories = TRUE;
+
+ openlog("gdmchooser", LOG_PID, LOG_DAEMON);
+
+ gnome_init("gdmchooser", VERSION, argc, argv);
+ gnome_sound_shutdown();
+
+ gdm_chooser_parse_config();
+ gdm_chooser_gui_init();
+ gdm_chooser_signals_init();
+
+ gdm_chooser_xdmcp_init();
+
+ gtk_main();
+
+ exit(EXIT_SUCCESS);
+}
+
+/* EOF */
diff --git a/gui/gdmchooser.h b/gui/gdmchooser.h
new file mode 100644
index 00000000..97ddfd04
--- /dev/null
+++ b/gui/gdmchooser.h
@@ -0,0 +1,40 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __GDM_CHOOSER_H__
+#define __GDM_CHOOSER_H__
+
+#include <gnome.h>
+
+/* If you (for some odd reason) have more than 16 interfaces in your
+ * machine, redefine this */
+
+#define MAXIF 16
+
+
+typedef struct _GdmChooserHost GdmChooserHost;
+
+struct _GdmChooserHost {
+ gchar *name;
+ gchar *desc;
+ GdkImlibImage *picture;
+};
+
+#endif /* __GDM_CHOOSER_H__ */
+
+/* EOF */
diff --git a/gui/gdmgreeter.c b/gui/gdmgreeter.c
new file mode 100644
index 00000000..2c55c722
--- /dev/null
+++ b/gui/gdmgreeter.c
@@ -0,0 +1,1713 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* gdmgreeter is the graphical login part of gdm, The Gnome Display
+ * Manager. The greeter runs as a dedicated gdm user and communicates
+ * with gdm through a pipe. Thus, all files used by the program must
+ * be accessible for `gdm' (or whatever you set the userid to in
+ * gdm.conf).
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "gdmgreeter.h"
+
+static const gchar RCSid[]="$Id$";
+
+extern gboolean gdm_file_check(gchar *caller, uid_t user, gchar *dir, gchar *file, gboolean absentok);
+
+gchar *gdm_greeter_session_lookup(gchar *session);
+gchar *gdm_greeter_language_lookup(gchar *language);
+static gdmUserType *gdm_greeter_user_alloc (gchar *logname, gint uid, gchar *homedir);
+
+
+gint GdmCompletion;
+gint GdmDebug;
+gint GdmDisplayBrowser;
+gint GdmDisplayLogo;
+gint GdmIconMaxHeight;
+gint GdmIconMaxWidth;
+gint GdmIconify;
+gint GdmNumberOfCols;
+gint GdmQuiver;
+gint GdmShutdownMenu;
+gint GdmUserMaxFile;
+gint GdmRelaxPerms=0;
+gchar *GdmSuspend;
+gchar *GdmGlobalImageDir;
+gchar *GdmLogoFilename;
+gchar *GdmMessageText;
+gchar *GdmNofaceImageFile;
+gchar *GdmConfigFilename=GDM_CONFIG_FILE;
+gchar *GdmSessionDir;
+gchar *GdmIconFile;
+gchar *GdmMessageFont;
+gchar *GdmLocaleFile;
+gchar *GdmDefaultLocale;
+gchar *GdmPidFile; /* Hack, not used in greeter */
+gchar *GdmDefaultPath; /* Hack Part II */
+gchar *GdmGtkRC;
+
+GtkWidget *greeterframe;
+GtkWidget *gdmMain;
+GtkWidget *logobox;
+GtkWidget *msgbox;
+GtkWidget *msglabel;
+GtkWidget *loginentry;
+GtkWidget *passwdentry;
+GtkWidget *greeter;
+GtkWidget *buttonpane;
+GtkWidget *entrypane;
+GdkWindow *rootwin;
+GtkWidget *win;
+GtkWidget *optionmenu;
+GtkWidget *sessmenu;
+GtkWidget *langmenu;
+GtkWidget *loginbutton;
+GtkWidget *optionbutton;
+GtkWidget *browser_hbox;
+
+gchar *login, *passwd;
+gchar *defsess = NULL;
+gchar *deflang = NULL;
+gchar *cursess = NULL;
+gchar *curlang = NULL;
+gchar *usrsess = NULL;
+gchar *usrlang = NULL;
+
+gboolean sessmatch=FALSE;
+gboolean langmatch=TRUE;
+gboolean sessmod=FALSE;
+gboolean langmod=TRUE;
+
+GCompletion *cmpl;
+GList *result;
+GList *users;
+GSList *languages=NULL;
+GSList *sessions=NULL;
+GdkImlibImage *nofaceimg;
+GnomeIconList *browser;
+
+
+
+/* Normal program termination */
+static void
+gdm_greeter_done(void)
+{
+ closelog();
+ gtk_main_quit();
+}
+
+
+/* Log formatted error message and exit */
+static void
+gdm_greeter_abort(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_ERR, s);
+
+ closelog();
+ g_print("%cA", 0x2);
+ exit(EXIT_FAILURE);
+}
+
+
+/* Show about dialog */
+static void
+gdm_greeter_about (void)
+{
+ const gchar *authors[] = {"Martin Kasper Petersen <mkp@mkp.net>", NULL};
+
+ GtkWidget *about = gnome_about_new ( _("Gnome Display Manager"),
+ "" VERSION "",
+ _("Copyright Martin K. Petersen (C) 1998, 1999"),
+ authors,
+ _("gdm manages local and remote displays and provides the user with a login window."),
+ NULL);
+ gtk_widget_show (about);
+}
+
+
+static gchar *
+gdm_parse_enriched_string(gchar *s)
+{
+ gchar cmd, *buffer, *start;
+ gchar hostbuf[256];
+ gchar *hostname, *temp1, *temp2, *display;
+
+ display=getenv("DISPLAY");
+
+ if(!display)
+ return(NULL);
+
+ temp1=strchr(display, '.');
+ temp2=strchr(display, ':');
+
+ if(temp1)
+ *temp1='\0';
+ else if(temp2)
+ *temp2='\0';
+ else
+ return(NULL); /* Display isn't */
+
+ gethostname(hostbuf, 255);
+ hostname=g_strdup(hostbuf);
+
+ if(!hostname)
+ hostname=g_strdup("Gnome");
+
+ if(strlen(s) > 1023) {
+ syslog(LOG_ERR, _("gdm_parse_enriched_string: String too long!"));
+ return(g_strconcat(_("Welcome to "), hostname, NULL));
+ }
+
+ if(!(buffer = g_malloc(4096))) {
+ syslog(LOG_ERR, _("gdm_parse_enriched_string: Could not malloc temporary buffer!"));
+ return(NULL);
+ }
+
+ start = buffer;
+
+ while(*s) {
+
+ if(*s=='%' && (cmd = s[1]) != 0) {
+ s+=2;
+
+ switch(cmd) {
+
+ case 'h':
+ memcpy(buffer, hostname, strlen(hostname));
+ buffer+=strlen(hostname);
+ break;
+
+ case 'd':
+ memcpy(buffer, display, strlen(display));
+ buffer+=strlen(display);
+ break;
+
+ case '%':
+ *buffer++='%';
+ break;
+
+ default:
+ break;
+ };
+ }
+ else
+ *buffer++=*s++;
+ }
+
+ *buffer=0;
+
+ return(g_strdup(start));
+}
+
+
+static void
+gdm_greeter_message_init(void)
+{
+ GtkStyle *style;
+ gchar *msg=NULL;
+
+ msg=gdm_parse_enriched_string(GdmMessageText);
+
+ msgbox = gtk_vbox_new(FALSE, 0);
+
+ if(msg) {
+ style = gtk_style_new();
+ gdk_font_unref(style->font);
+ style->font = gdk_font_load (GdmMessageFont);
+ gtk_widget_push_style(style);
+
+ msglabel = gtk_label_new(msg);
+ gtk_box_pack_start(GTK_BOX (msgbox), msglabel, TRUE, TRUE, 0);
+ gtk_widget_show(msglabel);
+ gtk_widget_pop_style();
+ }
+
+ gtk_widget_show_all(msgbox);
+}
+
+
+static void
+gdm_greeter_logo_init (void)
+{
+ GtkWidget *logo;
+ GtkWidget *frame;
+
+ if(access(GdmLogoFilename, R_OK)) {
+ syslog(LOG_WARNING, _("Logo not found. No image will be displayed!"));
+ }
+ else {
+ logo = gnome_pixmap_new_from_file (GdmLogoFilename);
+ gtk_widget_show(logo);
+
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(frame), logo);
+ gtk_widget_show(frame);
+
+ logobox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX (logobox),
+ frame, FALSE, FALSE, 0);
+ gtk_widget_show(logobox);
+ }
+}
+
+
+static void
+gdm_greeter_parse_config(void)
+{
+ struct stat unused;
+ gchar *display;
+
+ if(stat(GDM_CONFIG_FILE, &unused) == -1)
+ gdm_greeter_abort(_("gdm_greeter_parse_config: No configuration file: %s. Aborting."), GDM_CONFIG_FILE);
+
+ gnome_config_push_prefix ("=" GDM_CONFIG_FILE "=/");
+
+ GdmCompletion=gnome_config_get_int("appearance/Completion=1");
+ GdmDisplayBrowser=gnome_config_get_int("appearance/Browser=1");
+ GdmDisplayLogo=gnome_config_get_int("appearance/Logo=1");
+ GdmLogoFilename=gnome_config_get_string("appearance/LogoImage");
+ GdmQuiver=gnome_config_get_int("appearance/Quiver=1");
+ GdmIconify=gnome_config_get_int("appearance/iconify=1");
+ GdmIconFile=gnome_config_get_string("appearance/iconfile=gdm.xpm");
+ GdmNofaceImageFile= gnome_config_get_string("appearance/NoFaceImage");
+ GdmGlobalImageDir=gnome_config_get_string("appearance/GlobalImageDir");
+ GdmMessageFont=gnome_config_get_string("appearance/msgfont=-adobe-helvetica-bold-r-normal-*-*-180-*-*-*-*-*-*");
+ GdmGtkRC=gnome_config_get_string("appearance/gtkrc");
+
+ GdmShutdownMenu=gnome_config_get_int("system/ShutdownMenu=0");
+ GdmUserMaxFile=gnome_config_get_int("system/UserFileCutoffSize=65536");
+ GdmIconMaxWidth=gnome_config_get_int("system/UserIconMaxWidth=128");
+ GdmIconMaxHeight=gnome_config_get_int("system/UserIconMaxHeight=128");
+ GdmSuspend=g_strdup(gnome_config_get_string("system/SuspendCommand"));
+ GdmLocaleFile=g_strdup(gnome_config_get_string("system/LocaleFile=/usr/share/locale/locale.alias"));
+ GdmDefaultLocale=g_strdup(gnome_config_get_string("system/DefaultLocale=english"));
+
+ GdmMessageText=gnome_config_get_string(_("messages/welcome=Welcome to %h"));
+
+ GdmSessionDir=gnome_config_get_string("daemon/sessiondir");
+
+ GdmDebug=gnome_config_get_int("debug/enable=0");
+
+ gnome_config_pop_prefix ();
+
+ if(stat(GdmLocaleFile, &unused) == -1)
+ gdm_greeter_abort("gdm_greeter_parse_config: Could not open locale file %s. Aborting!", GdmLocaleFile);
+
+ /* Disable System menu on non-local displays */
+ display=getenv("DISPLAY");
+
+ if(!display)
+ gdm_greeter_abort("gdm_greeter_parse_config: DISPLAY variable not set!");
+
+ if(strncmp(display, ":", 1))
+ GdmShutdownMenu=0;
+}
+
+
+static gboolean
+gdm_greeter_query(gchar *msg)
+{
+ GtkWidget *req;
+
+ req=gnome_message_box_new(msg,
+ GNOME_MESSAGE_BOX_QUESTION,
+ GNOME_STOCK_BUTTON_YES,
+ GNOME_STOCK_BUTTON_NO,
+ NULL);
+
+ gtk_window_set_modal(GTK_WINDOW(req), TRUE);
+ return(!gnome_dialog_run(GNOME_DIALOG(req)));
+}
+
+
+static void
+gdm_greeter_info_handler(GtkWidget *widget, GtkWidget *dialog)
+{
+ GdkCursor *cursor;
+
+ cursor=gdk_cursor_new(GDK_LEFT_PTR);
+ gdk_window_set_cursor (gdmMain->window, cursor);
+ gdk_cursor_destroy(cursor);
+ gtk_widget_set_sensitive (gdmMain, TRUE);
+}
+
+
+static void
+gdm_greeter_info(gchar *msg)
+{
+ GtkWidget *req;
+
+ req=gnome_message_box_new(msg,
+ GNOME_MESSAGE_BOX_INFO,
+ GNOME_STOCK_BUTTON_OK,
+ NULL);
+
+ gnome_dialog_button_connect(GNOME_DIALOG(req),
+ 0,
+ gdm_greeter_info_handler,
+ NULL);
+
+ gtk_window_set_modal(GTK_WINDOW(req), TRUE);
+ gtk_widget_show_all(req);
+}
+
+
+static gboolean
+gdm_greeter_login (GtkWidget *widget, gpointer data)
+{
+ GdkCursor *cursor;
+
+ if(!strlen(gtk_entry_get_text(GTK_ENTRY(loginentry))))
+ return(TRUE);
+
+ cursor=gdk_cursor_new(GDK_WATCH);
+ gdk_window_set_cursor(gdmMain->window, cursor);
+ gdk_cursor_destroy(cursor);
+ gtk_widget_set_sensitive(gdmMain, FALSE);
+ gtk_widget_show(gdmMain);
+
+ g_print("%cU%s\n%s\n", 0x2, gtk_entry_get_text(GTK_ENTRY (loginentry)),
+ gtk_entry_get_text(GTK_ENTRY (passwdentry)));
+
+ return(TRUE);
+}
+
+
+static void
+gdm_greeter_sesslang_send(void)
+{
+ gboolean savesess=FALSE, savelang=FALSE;
+ static gchar msg[1024];
+
+ if(strcasecmp(cursess, usrsess)) {
+
+ if(sessmatch && sessmod) {
+ g_snprintf(msg, 1023,
+ _("You have chosen %s for this session, but your default setting is %s.\n" \
+ "Do you wish to make %s the default for future sessions?"),
+ cursess, usrsess, cursess);
+ savesess=gdm_greeter_query(msg);
+ }
+
+ if(!sessmatch && sessmod) {
+ g_snprintf(msg, 1023,
+ _("Your previous session type %s is not installed on this machine.\n" \
+ "Do you wish to make %s the default for future sessions?"),
+ usrsess, cursess);
+ savesess=gdm_greeter_query(msg);
+ }
+
+ if(!sessmatch && !sessmod) {
+ g_snprintf(msg, 1023,
+ _("Your previous session type %s is not installed on this machine.\n" \
+ "You will be logged in using the %s environment."),
+ usrsess, cursess);
+ gdm_greeter_info(msg);
+ }
+ }
+ else
+ savesess=TRUE;
+
+ if(strcasecmp(curlang, usrlang)) {
+
+ if(langmatch && langmod) {
+ g_snprintf(msg, 1023,
+ _("You have chosen the language %s for this session, but your default setting is %s.\n" \
+ "Do you wish to make %s the default language for future sessions?"),
+ curlang, usrlang, curlang);
+ savelang=gdm_greeter_query(msg);
+ }
+
+ if(!langmatch && langmod) {
+ g_snprintf(msg, 1023,
+ _("Your previous language %s is not installed on this machine.\n" \
+ "Do you wish to make %s the default language for future sessions?"),
+ usrlang, curlang);
+ savelang=gdm_greeter_query(msg);
+ }
+
+ if(!langmatch && !langmod) {
+ g_snprintf(msg, 1023,
+ _("Your previous language %s is not installed on this machine.\n" \
+ "Your environment will be %s."),
+ usrlang, curlang);
+ gdm_greeter_info(msg);
+ }
+ }
+ else
+ savelang=TRUE;
+
+ g_print("%c%s\n%d\n%s\n%d\n", 0x3, cursess, savesess, curlang, savelang);
+}
+
+
+static void
+gdm_greeter_invalid_passwd_req (void)
+{
+ gint i;
+ gint x,y;
+
+ /* FIXME: esound! */
+ if(GdmQuiver) {
+ gdk_window_get_position(greeter->window, &x, &y);
+
+ for (i=32 ; i > 0 ; i=i/2) {
+ gdk_window_move(greeter->window, i+x, y);
+ gdk_window_move(greeter->window, x, y);
+ gdk_window_move(greeter->window, -i+x, y);
+ gdk_window_move(greeter->window, x, y);
+ }
+ }
+
+ gdm_greeter_info(_("Invalid username or password!"));
+
+ gtk_window_set_focus(GTK_WINDOW (greeter), passwdentry);
+}
+
+
+static void
+gdm_greeter_reboot(gint reply, gpointer data)
+{
+ if (reply == GNOME_YES) {
+ closelog();
+ g_print("%cR", 0x2);
+ gtk_main_quit();
+ }
+
+ gtk_widget_set_sensitive(gdmMain, TRUE);
+ gtk_window_set_focus(GTK_WINDOW(greeter), passwdentry);
+}
+
+
+static gboolean
+gdm_greeter_reboot_handler(GtkWidget *widget, gpointer data)
+{
+ static GtkWidget *box=NULL;
+
+ gtk_widget_set_sensitive(gdmMain, FALSE);
+ box=gnome_question_dialog_modal(_("Are you sure you want to reboot the machine?"),
+ GTK_SIGNAL_FUNC (gdm_greeter_reboot),
+ NULL);
+ gtk_widget_show(box);
+
+ return(TRUE);
+}
+
+
+static void
+gdm_greeter_halt(gint reply, gpointer data)
+{
+ if (reply == GNOME_YES) {
+ closelog();
+ g_print("%cH", 0x2);
+ gtk_main_quit();
+ }
+
+ gtk_widget_set_sensitive(gdmMain, TRUE);
+ gtk_window_set_focus(GTK_WINDOW (greeter), passwdentry);
+}
+
+
+static gboolean
+gdm_greeter_halt_handler(GtkWidget *widget, gpointer data)
+{
+ static GtkWidget *box=NULL;
+
+ gtk_widget_set_sensitive (gdmMain, FALSE);
+ box=gnome_question_dialog_modal(_("Are you sure you want to halt the machine?"),
+ GTK_SIGNAL_FUNC (gdm_greeter_halt),
+ NULL);
+ gtk_widget_show(box);
+
+ return(TRUE);
+}
+
+
+static gboolean
+gdm_greeter_suspend_handler(GtkWidget *widget, int button, gpointer data)
+{
+ g_print("%cS", 0x2);
+
+ return(TRUE);
+}
+
+
+typedef struct _cursoroffset {gint x,y;} CursorOffset;
+
+
+static void
+gdm_greeter_icon_pressed(GtkWidget *widget, GdkEventButton *event)
+{
+ CursorOffset *p;
+
+ if(event->type == GDK_2BUTTON_PRESS) {
+ gtk_widget_destroy(win);
+ gdk_window_show(greeter->window);
+ return;
+ }
+
+ if (event->type != GDK_BUTTON_PRESS)
+ return;
+
+ p=gtk_object_get_user_data(GTK_OBJECT (widget));
+ p->x=(gint)event->x;
+ p->y=(gint)event->y;
+
+ gtk_grab_add(widget);
+ gdk_pointer_grab(widget->window, TRUE,
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK,
+ NULL, NULL, 0);
+}
+
+
+static void
+gdm_greeter_icon_released(GtkWidget *widget)
+{
+ gtk_grab_remove(widget);
+ gdk_pointer_ungrab(0);
+}
+
+
+static void
+gdm_greeter_icon_motion(GtkWidget *widget, GdkEventMotion *event)
+{
+ gint xp, yp;
+ CursorOffset *p;
+ GdkModifierType mask;
+
+ p=gtk_object_get_user_data(GTK_OBJECT (widget));
+ gdk_window_get_pointer(rootwin, &xp, &yp, &mask);
+ gtk_widget_set_uposition(widget, xp-p->x, yp-p->y);
+}
+
+
+static gboolean
+gdm_greeter_iconify_handler(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *fixed;
+ GtkWidget *icon;
+ GdkGC *gc;
+ GtkStyle *style;
+ CursorOffset *icon_pos;
+ gint rw, rh, iw, ih;
+
+ gdk_window_hide(greeter->window);
+ style=gtk_widget_get_default_style();
+ gc=style->black_gc;
+ win=gtk_window_new(GTK_WINDOW_POPUP);
+
+ gtk_widget_set_events(win,
+ gtk_widget_get_events(win) |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ gtk_widget_realize(win);
+
+ fixed=gtk_fixed_new();
+ gtk_container_add(GTK_CONTAINER (win), fixed);
+ gtk_widget_show(fixed);
+
+ icon=gnome_pixmap_new_from_file (GdmIconFile);
+ gdk_window_get_size ((GdkWindow *) GNOME_PIXMAP (icon)->pixmap, &iw, &ih);
+
+ gtk_fixed_put(GTK_FIXED (fixed), icon, 0, 0);
+ gtk_widget_show(icon);
+
+ gtk_signal_connect(GTK_OBJECT (win), "button_press_event",
+ GTK_SIGNAL_FUNC (gdm_greeter_icon_pressed),NULL);
+ gtk_signal_connect(GTK_OBJECT (win), "button_release_event",
+ GTK_SIGNAL_FUNC (gdm_greeter_icon_released),NULL);
+ gtk_signal_connect(GTK_OBJECT (win), "motion_notify_event",
+ GTK_SIGNAL_FUNC (gdm_greeter_icon_motion),NULL);
+
+ icon_pos=g_new(CursorOffset, 1);
+ gtk_object_set_user_data(GTK_OBJECT(win), icon_pos);
+
+ gtk_widget_show(win);
+
+ rw=gdk_screen_width();
+ rh=gdk_screen_height();
+
+ gtk_widget_set_uposition(win, rw-iw, rh-ih);
+
+ return(TRUE);
+}
+
+
+static gboolean
+gdm_greeter_opt_button_handler (GtkWidget *widget, GdkEvent *event)
+{
+ if (event->type == GDK_BUTTON_PRESS) {
+ GdkEventButton *bevent = (GdkEventButton *) event;
+ gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL,
+ bevent->button, bevent->time);
+ return(TRUE);
+ }
+
+ /* This code will probably never be reached */
+ if (event->type == GDK_KEY_PRESS) {
+ GdkEventKey *kevent = (GdkEventKey *) event;
+ switch(kevent->keyval) {
+
+ case GDK_Left:
+ gtk_window_set_focus(GTK_WINDOW (greeter), loginbutton);
+ return(TRUE);
+
+ case GDK_Right:
+ return(TRUE);
+
+ case GDK_Up:
+ case GDK_Tab:
+ gtk_window_set_focus(GTK_WINDOW (greeter), passwdentry);
+ return(TRUE);
+
+ case GDK_Down:
+ gtk_window_set_focus(GTK_WINDOW (greeter), loginentry);
+ return(TRUE);
+
+ default:
+ break;
+ }
+ }
+
+ return(FALSE);
+}
+
+
+static gboolean
+gdm_greeter_login_key_handler (GtkWidget *widget, GdkEventKey *event)
+{
+ switch(event->keyval) {
+
+ case GDK_Return:
+ gdm_greeter_login(NULL, NULL);
+ break;
+
+ case GDK_Up:
+ case GDK_Tab:
+ case GDK_Left:
+ gtk_signal_emit_stop_by_name(GTK_OBJECT (loginbutton), "key_press_event");
+ gtk_window_set_focus(GTK_WINDOW (greeter), passwdentry);
+ break;
+
+ case GDK_Down:
+ gtk_signal_emit_stop_by_name(GTK_OBJECT (loginbutton), "key_press_event");
+ gtk_window_set_focus(GTK_WINDOW (greeter), loginentry);
+ break;
+
+ case GDK_Right:
+ gtk_signal_emit_stop_by_name(GTK_OBJECT (loginbutton), "key_press_event");
+ break;
+
+ default:
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+gchar *
+gdm_greeter_session_lookup(gchar *session)
+{
+ GSList *sess=sessions;
+ gchar *temp;
+
+ if(!session) {
+ sessmatch=TRUE;
+ return(defsess);
+ }
+
+ while(sess) {
+ gtk_label_get(GTK_LABEL(GTK_BIN(sess->data)->child), &temp);
+
+ if(!strcmp(temp, session)) {
+ sessmatch=TRUE;
+ return(g_strdup(session));
+ }
+
+ sess=sess->next;
+ }
+
+ sessmatch=FALSE;
+ return(defsess);
+}
+
+
+static void
+gdm_greeter_session_select(GtkWidget *widget, gchar *sess)
+{
+ gchar *temp;
+
+ if(!widget || !sess)
+ return;
+
+ gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &temp);
+
+ if(!strcasecmp(temp, sess))
+ gtk_check_menu_item_set_state (GTK_CHECK_MENU_ITEM (widget), TRUE);
+}
+
+
+static void
+gdm_greeter_session_handler (GtkWidget *widget)
+{
+ gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &cursess);
+ sessmod=TRUE;
+}
+
+
+static void
+gdm_greeter_session_init(GtkWidget *parent)
+{
+ DIR *sessdir;
+ struct dirent *dent;
+ struct stat statbuf;
+ gint linklen;
+ GtkWidget *submenu, *item;
+
+ /* Check that session dir is readable */
+ if (access(GdmSessionDir, R_OK|X_OK))
+ gdm_greeter_abort(_("gdm_greeter_session_init: Session script directory not found!"));
+
+ /* Create submenu */
+ submenu=gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent), submenu);
+
+ /* Read directory entries in session dir */
+ sessdir=opendir(GdmSessionDir);
+ dent=readdir(sessdir);
+
+ while(dent != NULL) {
+ gchar *s;
+
+ s=g_strconcat(GdmSessionDir, "/", dent->d_name, NULL);
+ lstat(s, &statbuf);
+
+ /* If default session link exists, find out what it points to */
+ if(S_ISLNK(statbuf.st_mode) && !strcasecmp(dent->d_name, "default")) {
+ gchar t[_POSIX_PATH_MAX];
+
+ linklen=readlink(s, t, _POSIX_PATH_MAX);
+ t[linklen]=0;
+ defsess=g_strdup(t);
+ }
+
+ /* If session script is readable/executable add it to the list */
+ if(S_ISREG(statbuf.st_mode)) {
+
+ if((statbuf.st_mode & (S_IRUSR|S_IXUSR)) == (S_IRUSR|S_IXUSR) &&
+ (statbuf.st_mode & (S_IRGRP|S_IXGRP)) == (S_IRGRP|S_IXGRP) &&
+ (statbuf.st_mode & (S_IROTH|S_IXOTH)) == (S_IROTH|S_IXOTH))
+ {
+ item=gtk_radio_menu_item_new_with_label(sessions, dent->d_name);
+ sessions=gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM (item));
+ gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM (item), TRUE);
+ gtk_menu_append(GTK_MENU (submenu), item);
+
+ gtk_signal_connect(GTK_OBJECT (item), "activate",
+ GTK_SIGNAL_FUNC (gdm_greeter_session_handler), NULL);
+
+ gtk_widget_show(item);
+ }
+ else
+ syslog(LOG_ERR, "Wrong permissions on %s/%s. Should be readable/executable for all.",
+ GdmSessionDir, dent->d_name);
+
+ }
+
+ dent=readdir(sessdir);
+ g_free(s);
+ }
+
+ if(!g_slist_length(sessions))
+ gdm_greeter_abort(_("No session scripts found. Aborting!"));
+
+ if(!defsess) {
+ gtk_label_get(GTK_LABEL(GTK_BIN(g_slist_nth_data(sessions, 0))->child), &defsess);
+ syslog(LOG_WARNING, _("No default session link found. Using %s.\n"), defsess);
+ }
+
+}
+
+
+gchar *
+gdm_greeter_language_lookup(gchar *language)
+{
+ GSList *lang=languages;
+ gchar *temp;
+
+ if(!language) {
+ langmatch=TRUE;
+ return(deflang);
+ }
+
+ while(lang) {
+ gtk_label_get(GTK_LABEL(GTK_BIN(lang->data)->child), &temp);
+
+ if(!strcasecmp(temp, language)) {
+ langmatch=TRUE;
+ return(g_strdup(language));
+ }
+
+ lang=lang->next;
+ }
+
+ langmatch=FALSE;
+ return(deflang);
+}
+
+
+static void
+gdm_greeter_language_select(GtkWidget *widget, gchar *lang)
+{
+ gchar *temp;
+
+ if(!widget || !lang)
+ return;
+
+ gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &temp);
+
+ if(!strcasecmp(temp, lang))
+ gtk_check_menu_item_set_state (GTK_CHECK_MENU_ITEM (widget), TRUE);
+}
+
+
+static void
+gdm_greeter_language_handler (GtkWidget *widget)
+{
+ gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &curlang);
+ langmod=TRUE;
+}
+
+
+static void
+gdm_greeter_language_init(GtkWidget *parent)
+{
+ GtkWidget *submenu, *item;
+ FILE *langlist;
+ char curline[256];
+ char *ctmp, *ctmp1, *ctmp2;
+
+ deflang=GdmDefaultLocale;
+
+ submenu = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent), submenu);
+
+ langlist = fopen(GdmLocaleFile, "r");
+
+ item = gtk_radio_menu_item_new_with_label(NULL, "English");
+ languages = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(item));
+ gtk_widget_show(item);
+
+ gtk_container_add(GTK_CONTAINER(submenu), item);
+ gtk_signal_connect(GTK_OBJECT(item), "activate", gdm_greeter_language_handler, NULL);
+
+ while(fgets(curline, sizeof(curline), langlist)) {
+ if(!isalpha(curline[0])) continue;
+
+ ctmp1 = strchr(curline, ' ');
+ ctmp2 = strchr(curline, '\t');
+ ctmp = curline + strlen(curline) - 1;
+ if(ctmp1 && (ctmp1 < ctmp))
+ ctmp = ctmp1;
+ if(ctmp2 && (ctmp2 < ctmp))
+ ctmp = ctmp2;
+ *ctmp = '\0';
+ curline[0] = toupper(curline[0]);
+
+ item = gtk_radio_menu_item_new_with_label(languages, curline);
+ languages = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(item));
+ gtk_widget_show(item);
+
+ gtk_container_add(GTK_CONTAINER(submenu), item);
+ gtk_signal_connect(GTK_OBJECT(item), "activate", gdm_greeter_language_handler, NULL);
+ }
+
+ fclose(langlist);
+}
+
+
+static void
+gdm_greeter_sl_update(gdmUserType *user)
+{
+ gboolean fileok;
+ gchar *dir=NULL, *cfg=NULL;
+
+ /* Check if ~user/.gnome/gdm passes sanity check */
+ dir=g_strconcat(user->homedir, "/.gnome", NULL);
+ fileok=gdm_file_check("gdm_greeter_sl_update", user->uid, dir, "gdm", TRUE);
+ g_free(dir);
+
+ /* Find user's last session and language if available */
+ if(fileok) {
+ cfg=g_strconcat("=", user->homedir, "/.gnome/gdm=/session/last", NULL);
+ usrsess=gnome_config_get_string(cfg);
+ g_free(cfg);
+
+ cfg=g_strconcat("=", user->homedir, "/.gnome/gdm=/session/lang", NULL);
+ usrlang=gnome_config_get_string(cfg);
+ g_free(cfg);
+ }
+
+ sessmatch=FALSE;
+ sessmod=FALSE;
+ cursess=gdm_greeter_session_lookup(usrsess);
+
+ if(!usrsess)
+ usrsess=g_strdup(cursess);
+
+ g_slist_foreach(sessions, (GFunc) gdm_greeter_session_select, cursess);
+ gtk_widget_set_sensitive (sessmenu, TRUE);
+
+ langmatch=FALSE;
+ langmod=FALSE;
+ curlang=gdm_greeter_language_lookup(usrlang);
+
+ if(!usrlang)
+ if(curlang)
+ usrlang=g_strdup(curlang);
+ else
+ usrlang=gdm_greeter_language_lookup("english");
+
+ g_slist_foreach(languages, (GFunc) gdm_greeter_language_select, curlang);
+ gtk_widget_set_sensitive (langmenu, TRUE);
+
+ /* Widget magic */
+ gtk_entry_set_text (GTK_ENTRY (loginentry), user->login);
+ gtk_window_set_focus(GTK_WINDOW (greeter), passwdentry);
+}
+
+
+static void
+gdm_greeter_buttons_init(void)
+{
+ GtkWidget *submenu, *item;
+
+ /* Login button */
+ loginbutton = gtk_button_new_with_label(_("Login"));
+ gtk_signal_connect(GTK_OBJECT (loginbutton), "clicked",
+ GTK_SIGNAL_FUNC (gdm_greeter_login), NULL);
+ gtk_signal_connect(GTK_OBJECT (loginbutton), "key_press_event",
+ GTK_SIGNAL_FUNC (gdm_greeter_login_key_handler), NULL);
+ GTK_WIDGET_SET_FLAGS(loginbutton, GTK_CAN_DEFAULT);
+ gtk_widget_show(loginbutton);
+
+ /* Option button drop down menu */
+ optionmenu = gtk_menu_new();
+
+ /* Init sessions menu */
+ sessmenu = gtk_menu_item_new_with_label(_("Sessions"));
+ gtk_menu_append(GTK_MENU (optionmenu), sessmenu);
+ gdm_greeter_session_init(sessmenu);
+ gtk_widget_show(sessmenu);
+ gtk_widget_set_sensitive (sessmenu, FALSE);
+
+ /* Language selection support */
+ langmenu = gtk_menu_item_new_with_label (_("Languages"));
+ gtk_menu_append(GTK_MENU (optionmenu), langmenu);
+ gdm_greeter_language_init(langmenu);
+ gtk_widget_show(langmenu);
+ gtk_widget_set_sensitive (langmenu, FALSE);
+
+ /* If sysadmin enabled shutdown menu */
+ if (GdmShutdownMenu) {
+ submenu = gtk_menu_new();
+
+ item = gtk_menu_item_new_with_label (_("Reboot..."));
+ gtk_menu_append(GTK_MENU (submenu), item);
+ gtk_signal_connect(GTK_OBJECT (item), "activate",
+ GTK_SIGNAL_FUNC (gdm_greeter_reboot_handler), NULL);
+ gtk_widget_show(item);
+
+ item = gtk_menu_item_new_with_label (_("Halt..."));
+ gtk_menu_append(GTK_MENU (submenu), item);
+ gtk_signal_connect(GTK_OBJECT (item), "activate",
+ GTK_SIGNAL_FUNC (gdm_greeter_halt_handler), NULL);
+ gtk_widget_show(item);
+
+ if(GdmSuspend) {
+ item = gtk_menu_item_new_with_label (_("Suspend"));
+ gtk_menu_append(GTK_MENU (submenu), item);
+ gtk_signal_connect(GTK_OBJECT (item), "activate",
+ GTK_SIGNAL_FUNC (gdm_greeter_suspend_handler), NULL);
+ gtk_widget_show(item);
+ }
+
+ item = gtk_menu_item_new_with_label (_("System"));
+ gtk_menu_append(GTK_MENU (optionmenu), item);
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+ gtk_widget_show(item);
+ }
+
+ if(GdmIconify) {
+ if(access(GdmIconFile, R_OK)) {
+ syslog(LOG_WARNING, _("Can't open icon file: %s. Suspending iconify feature!"), GdmIconFile);
+ GdmIconify=0;
+ }
+ else {
+ item = gtk_menu_item_new_with_label (_("Iconify"));
+ gtk_menu_append(GTK_MENU (optionmenu), item);
+ gtk_signal_connect(GTK_OBJECT (item), "activate",
+ GTK_SIGNAL_FUNC (gdm_greeter_iconify_handler), NULL);
+ gtk_widget_show(item);
+ }
+ }
+
+ /* Option button */
+ optionbutton = gtk_button_new_with_label(_("Options..."));
+ gtk_signal_connect_object(GTK_OBJECT (optionbutton), "event",
+ GTK_SIGNAL_FUNC (gdm_greeter_opt_button_handler),
+ GTK_OBJECT(optionmenu));
+ GTK_WIDGET_SET_FLAGS(optionbutton, GTK_CAN_DEFAULT);
+ gtk_widget_show(optionbutton);
+
+ buttonpane = gtk_hbox_new(TRUE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER (buttonpane), 0);
+
+ gtk_box_pack_start(GTK_BOX (buttonpane),
+ loginbutton, TRUE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX (buttonpane),
+ optionbutton, TRUE, TRUE, 5);
+
+ gtk_window_set_default(GTK_WINDOW(greeter), GTK_WIDGET(loginbutton));
+ gtk_widget_show_all(buttonpane);
+}
+
+
+static gboolean
+gdm_greeter_browser_select(GtkWidget *widget, gint selected, GdkEvent *event)
+{
+ gdmUserType *user;
+
+ if(!event)
+ return(TRUE);
+ else
+ switch(event->type) {
+
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ user=g_list_nth_data(result, selected);
+ gdm_greeter_sl_update(user);
+ break;
+
+ default:
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+static gboolean
+gdm_greeter_browser_unselect(GtkWidget *widget, gint selected, GdkEvent *event)
+{
+ if(event) {
+ switch(event->type) {
+
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ gnome_icon_list_unselect_all((GnomeIconList *) widget, NULL, NULL);
+ gtk_entry_set_text (GTK_ENTRY (loginentry), "");
+ gtk_window_set_focus(GTK_WINDOW (greeter), loginentry);
+ gtk_widget_set_sensitive (sessmenu, FALSE);
+ gtk_widget_set_sensitive (langmenu, FALSE);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return(TRUE);
+}
+
+
+static void
+gdm_greeter_browser_foreach (gdmUserType *user)
+{
+ if(browser)
+ gnome_icon_list_append_imlib (browser, user->picture, user->login);
+}
+
+
+static void
+gdm_greeter_browser_init (void)
+{
+ GtkWidget *scrollbar;
+ gchar *lmatch=NULL;
+ GtkWidget *bframe;
+ GtkStyle *style;
+ GdkColor bbg = { 0, 0xFFFF, 0xFFFF, 0xFFFF };
+
+ /*
+ * Create icon list and scrollbar
+ */
+
+ style = gtk_style_copy (greeter->style);
+ style->bg[GTK_STATE_NORMAL] = bbg;
+ gtk_widget_push_style(style);
+
+ browser = GNOME_ICON_LIST (gnome_icon_list_new (GdmIconMaxWidth+20, NULL, FALSE));
+ gnome_icon_list_freeze (GNOME_ICON_LIST (browser));
+ gtk_widget_pop_style();
+
+ scrollbar = gtk_vscrollbar_new (browser->adj);
+ bframe = gtk_frame_new(NULL);
+
+ gtk_frame_set_shadow_type(GTK_FRAME (bframe), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(bframe), GTK_WIDGET(browser));
+
+ browser_hbox = gtk_hbox_new (0, 0);
+ gtk_box_pack_start (GTK_BOX (browser_hbox), GTK_WIDGET (bframe), 1, 1, 0);
+ gtk_box_pack_start (GTK_BOX (browser_hbox), scrollbar, 0, 0, 0);
+
+ gnome_icon_list_set_separators (browser, " /-_.");
+ gnome_icon_list_set_row_spacing (browser, 2);
+ gnome_icon_list_set_col_spacing (browser, 2);
+ gnome_icon_list_set_icon_border (browser, 2);
+ gnome_icon_list_set_text_spacing (browser, 2);
+ gnome_icon_list_set_selection_mode (browser, GTK_SELECTION_SINGLE);
+
+ gtk_signal_connect (GTK_OBJECT (browser), "select_icon",
+ GTK_SIGNAL_FUNC (gdm_greeter_browser_select), NULL);
+
+ gtk_signal_connect (GTK_OBJECT (browser), "unselect_icon",
+ GTK_SIGNAL_FUNC (gdm_greeter_browser_unselect), NULL);
+
+ result = g_completion_complete(cmpl, "", &lmatch);
+
+ if(lmatch)
+ gtk_entry_set_text(GTK_ENTRY (loginentry), lmatch);
+
+ gnome_icon_list_clear (browser);
+ g_list_foreach(users, (GFunc) gdm_greeter_browser_foreach, NULL);
+ gnome_icon_list_thaw (browser);
+ gtk_widget_show_all(GTK_WIDGET(browser_hbox));
+}
+
+
+static gboolean
+gdm_greeter_login_entry_handler (GtkWidget *widget, GdkEventKey *event)
+{
+ gchar *lmatch=NULL;
+ gchar *entry=NULL;
+ gint i;
+ gdmUserType *user=NULL;
+
+ gtk_widget_set_sensitive (sessmenu, FALSE);
+ gtk_widget_set_sensitive (langmenu, FALSE);
+
+ switch(event->keyval) {
+
+ case GDK_Return:
+ case GDK_Down:
+ case GDK_Tab: /* Where the nightmare begins */
+
+ gtk_signal_emit_stop_by_name(GTK_OBJECT (loginentry), "key_press_event");
+
+ entry=gtk_entry_get_text(GTK_ENTRY (loginentry));
+
+ if(!strlen(entry))
+ entry=g_strdup("");
+
+ result = g_completion_complete(cmpl, entry, &lmatch);
+
+ /* Unambiguous match => Move to passwd field and enable
+ * session selection
+ */
+ if(g_list_length(result) == 1) {
+ gtk_window_set_focus(GTK_WINDOW (greeter), passwdentry);
+ gtk_widget_set_sensitive (sessmenu, TRUE);
+ gtk_widget_set_sensitive (langmenu, TRUE);
+ }
+
+ /* One or no completions => Show all users */
+ if(g_list_length(result) <= 1)
+ result = g_completion_complete(cmpl, "", NULL);
+
+ /* If partial match write greatest common string in login
+ * field
+ */
+ if(lmatch)
+ gtk_entry_set_text(GTK_ENTRY (loginentry), lmatch);
+
+ if(GdmDisplayBrowser) {
+ gnome_icon_list_freeze(browser);
+ gnome_icon_list_clear(browser);
+ g_list_foreach(result, (GFunc) gdm_greeter_browser_foreach, NULL);
+ gnome_icon_list_thaw (browser);
+ }
+
+ for (i=0 ; i<g_list_length(result) ; i++) {
+ user=g_list_nth_data(result, i);
+
+ if(!strcasecmp(gtk_entry_get_text(GTK_ENTRY(loginentry)), user->login)) {
+
+ if(GdmDisplayBrowser) {
+ gnome_icon_list_moveto(browser, i, 0.5);
+ gnome_icon_list_select_icon(browser, i);
+ }
+
+ gdm_greeter_sl_update(user);
+ }
+ }
+
+ break;
+
+ case GDK_Up:
+ gtk_signal_emit_stop_by_name(GTK_OBJECT (loginentry), "key_press_event");
+ break;
+
+ case GDK_F1:
+ gdm_greeter_about();
+ break;
+
+ default:
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+static gboolean
+gdm_greeter_passwd_entry_handler (GtkWidget *widget, GdkEventKey *event)
+{
+ switch(event->keyval) {
+
+ case GDK_Return:
+ gdm_greeter_login(NULL, NULL);
+ break;
+
+ case GDK_Up:
+ case GDK_Tab:
+ gtk_signal_emit_stop_by_name(GTK_OBJECT (passwdentry), "key_press_event");
+ gtk_window_set_focus(GTK_WINDOW (greeter), loginentry);
+ break;
+
+ case GDK_Down:
+ gtk_signal_emit_stop_by_name(GTK_OBJECT (passwdentry), "key_press_event");
+ break;
+
+ default:
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+static void
+gdm_greeter_entry_init(void)
+{
+ GtkWidget *topsep;
+ GtkWidget *botsep;
+ GtkWidget *labelvbox;
+ GtkWidget *loginlabel;
+ GtkWidget *passwdlabel;
+ GtkWidget *entryvbox;
+ GtkWidget *gdminputhbox;
+
+ entrypane = gtk_vbox_new(FALSE, 0);
+ gdminputhbox = gtk_hbox_new(FALSE, 10);
+ labelvbox = gtk_vbox_new(TRUE, 0);
+ entryvbox = gtk_vbox_new(TRUE, 0);
+
+ topsep = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX (entrypane), topsep,
+ FALSE, FALSE, 10);
+ gtk_widget_show (topsep);
+
+ loginlabel = gtk_label_new(_("Login:"));
+ gtk_misc_set_alignment (GTK_MISC (loginlabel), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX (labelvbox), loginlabel,
+ FALSE, FALSE, 5);
+ gtk_widget_show(loginlabel);
+
+ passwdlabel = gtk_label_new(_("Password:"));
+ gtk_misc_set_alignment (GTK_MISC (passwdlabel), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX (labelvbox), passwdlabel,
+ FALSE, FALSE, 0);
+ gtk_widget_show(passwdlabel);
+
+ loginentry = gtk_entry_new_with_max_length (32);
+ gtk_entry_set_text (GTK_ENTRY (loginentry), "");
+ gtk_entry_select_region (GTK_ENTRY (loginentry), 0,
+ GTK_ENTRY (loginentry)->text_length);
+ gtk_signal_connect_object(GTK_OBJECT (loginentry),
+ "key_press_event",
+ GTK_SIGNAL_FUNC (gdm_greeter_login_entry_handler),
+ NULL);
+
+ gtk_box_pack_start(GTK_BOX (entryvbox), loginentry,
+ FALSE, TRUE, 5);
+ gtk_widget_show(loginentry);
+
+ passwdentry = gtk_entry_new_with_max_length (32);
+ gtk_entry_set_text (GTK_ENTRY (passwdentry), "");
+ gtk_entry_set_visibility(GTK_ENTRY (passwdentry), FALSE);
+ gtk_signal_connect_object(GTK_OBJECT (passwdentry),
+ "key_press_event",
+ GTK_SIGNAL_FUNC (gdm_greeter_passwd_entry_handler),
+ NULL);
+ gtk_box_pack_start(GTK_BOX (entryvbox), passwdentry,
+ FALSE, TRUE, 5);
+ gtk_widget_show(passwdentry);
+
+ gtk_box_pack_start(GTK_BOX (gdminputhbox), labelvbox,
+ FALSE, FALSE, 10);
+ gtk_widget_show (labelvbox);
+
+ gtk_box_pack_start(GTK_BOX (gdminputhbox), entryvbox,
+ TRUE, TRUE, 10);
+ gtk_widget_show (entryvbox);
+
+ gtk_box_pack_start(GTK_BOX (entrypane), gdminputhbox,
+ FALSE, FALSE, 0);
+ gtk_widget_show (gdminputhbox);
+
+ botsep = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX (entrypane), botsep,
+ FALSE, FALSE, 10);
+ gtk_widget_show(botsep);
+
+ gtk_widget_show(entrypane);
+}
+
+
+gdmUserType *
+gdm_greeter_user_alloc (gchar *logname, gint uid, gchar *homedir)
+{
+ gdmUserType *user;
+ gchar *dir=NULL, *img=NULL;
+ gboolean fileok;
+ GdkImlibImage *imlibimg=NULL;
+ gint w, h;
+
+ /* Allocate mem for user info struct */
+ user=g_malloc(sizeof(gdmUserType));
+
+ if(!user)
+ return(NULL);
+
+ user->uid=uid;
+ user->login=g_strdup(logname);
+ user->homedir=g_strdup(homedir);
+
+ /* If browser enabled choose an appropriate picture */
+ if(GdmDisplayBrowser) {
+
+ /* Check if ~user/.gnome/photo passes sanity check */
+ dir=g_strconcat(homedir, "/.gnome", NULL);
+ fileok=gdm_file_check("gdm_greeter_user_alloc", uid, dir, "photo", FALSE);
+ g_free(dir);
+
+ /* If user's picture passed sanity check/size cutoff value load it */
+ if(fileok) {
+ img=g_strconcat(homedir, "/.gnome/photo", NULL);
+ imlibimg=gdk_imlib_load_image(img);
+ g_free(img);
+ }
+ else {
+ img=g_strconcat(GdmGlobalImageDir, "/", logname, NULL);
+ if (!access(img, R_OK))
+ imlibimg=gdk_imlib_load_image(img);
+ g_free(img);
+ }
+
+ if(imlibimg) {
+ w=imlibimg->rgb_width;
+ h=imlibimg->rgb_height;
+
+ if(w>h && w>GdmIconMaxWidth) {
+ h=h*((gfloat) GdmIconMaxWidth/w);
+ w=GdmIconMaxWidth;
+ }
+ else if(h>GdmIconMaxHeight) {
+ w=w*((gfloat) GdmIconMaxHeight/h);
+ h=GdmIconMaxHeight;
+ }
+
+ user->picture=gdk_imlib_clone_scaled_image(imlibimg, w, h);
+
+ gdk_imlib_destroy_image(imlibimg);
+ }
+ else
+ user->picture=nofaceimg;
+
+ }
+
+ return (user);
+}
+
+
+static gint
+gdm_greeter_sort_func(gpointer d1, gpointer d2)
+{
+ gdmUserType *a=d1;
+ gdmUserType *b=d2;
+
+ return strcmp(a->login, b->login);
+}
+
+
+static gchar *
+gdm_greeter_complete_func(gpointer d1)
+{
+ gdmUserType *a=d1;
+
+ return (a->login);
+}
+
+
+static gint
+gdm_greeter_check_shell (gchar *usersh)
+{
+ gint found=0;
+ gchar *csh;
+
+ setusershell();
+
+ while((csh=getusershell()) != NULL)
+ if(!strcmp(csh, usersh))
+ found=1;
+
+ endusershell();
+
+ return(found);
+}
+
+
+static void
+gdm_greeter_users_init (void)
+{
+ gdmUserType *user;
+ struct passwd *pwent;
+
+ if(GdmDisplayBrowser) {
+ if(access(GdmNofaceImageFile, R_OK)) {
+ syslog(LOG_WARNING, _("Can't open NofaceImageFile: %s. Suspending face browser!"), GdmNofaceImageFile);
+ GdmDisplayBrowser=0;
+ }
+ else
+ nofaceimg=gdk_imlib_load_image(GdmNofaceImageFile);
+ }
+
+ pwent = getpwent();
+
+ while (pwent != NULL) {
+
+ if (pwent->pw_shell && gdm_greeter_check_shell(pwent->pw_shell)) {
+
+ user=gdm_greeter_user_alloc(pwent->pw_name,
+ pwent->pw_uid,
+ pwent->pw_dir);
+ if(user)
+ users=g_list_insert_sorted(users,
+ user,
+ (GCompareFunc) gdm_greeter_sort_func);
+ }
+
+ pwent = getpwent();
+ }
+
+ cmpl = g_completion_new ((GCompletionFunc) gdm_greeter_complete_func);
+
+ /* FIXME: Gross hack */
+ users = g_list_reverse(users);
+ g_completion_add_items (cmpl, users);
+ users = g_list_reverse(users);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ struct sigaction usr1, usr2, hup;
+ sigset_t mask;
+ GtkWidget *gdmLogoCtrlHbox;
+ GtkWidget *gdmCtrlVbox;
+
+ /* Avoid creating ~gdm/.gnome stuff */
+ gnome_do_not_create_directories = TRUE;
+
+ openlog("gdmgreeter", LOG_PID, LOG_DAEMON);
+
+ gnome_init("gdmgreeter", VERSION, argc, argv);
+ gnome_sound_shutdown ();
+
+ gdm_greeter_parse_config();
+
+ /* If completion is disabled => Disable browser */
+ /* if(!GdmCompletion)
+ GdmDisplayBrowser=FALSE; */
+
+ /* If browser is enabled => Force completion */
+ /* if(GdmDisplayBrowser) */
+
+ /* Force completion until PAM conversation function is implemented */
+ GdmCompletion=TRUE;
+
+ if(GdmCompletion)
+ gdm_greeter_users_init();
+
+ if(GdmGtkRC)
+ gtk_rc_parse(GdmGtkRC);
+
+ greeter = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_container_border_width (GTK_CONTAINER (greeter), 0);
+
+ greeterframe = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME (greeterframe), GTK_SHADOW_OUT);
+ gtk_container_border_width (GTK_CONTAINER (greeterframe), 0);
+ gtk_container_add(GTK_CONTAINER (greeter), greeterframe);
+
+ gdmMain = gtk_vbox_new(FALSE, 20);
+ gtk_container_border_width (GTK_CONTAINER (gdmMain), 0);
+ gtk_container_add(GTK_CONTAINER (greeterframe), gdmMain);
+
+ if(GdmDisplayBrowser) {
+ gdm_greeter_browser_init();
+ gtk_box_pack_start(GTK_BOX (gdmMain),
+ GTK_WIDGET(browser_hbox), TRUE, TRUE, 0);
+ }
+
+ gdmLogoCtrlHbox = gtk_hbox_new(FALSE, 10);
+ gtk_container_border_width (GTK_CONTAINER (gdmMain), 20);
+ gtk_box_pack_end(GTK_BOX (gdmMain),
+ gdmLogoCtrlHbox, FALSE, FALSE, 0);
+
+ if ((GdmDisplayLogo) && (GdmLogoFilename)) {
+ gdm_greeter_logo_init();
+ gtk_box_pack_start(GTK_BOX (gdmLogoCtrlHbox),
+ logobox, FALSE, FALSE, 0);
+ }
+
+ gdmCtrlVbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER (gdmLogoCtrlHbox), gdmCtrlVbox);
+
+ gdm_greeter_message_init();
+ gtk_box_pack_start(GTK_BOX (gdmCtrlVbox),
+ msgbox, TRUE, FALSE, 0);
+
+ gdm_greeter_buttons_init();
+ gtk_box_pack_end(GTK_BOX (gdmCtrlVbox),
+ buttonpane, FALSE, FALSE, 0);
+
+ gdm_greeter_entry_init();
+ gtk_box_pack_end(GTK_BOX (gdmCtrlVbox),
+ entrypane, FALSE, FALSE, 0);
+
+ gtk_widget_show(gdmCtrlVbox);
+ gtk_widget_show(gdmLogoCtrlHbox);
+ gtk_widget_show(gdmMain);
+ gtk_widget_show(greeterframe);
+
+ gtk_window_set_policy(GTK_WINDOW (greeter), 1, 1, 1);
+ gtk_window_set_focus(GTK_WINDOW (greeter), loginentry);
+ gtk_window_activate_focus(GTK_WINDOW (greeter));
+ gtk_widget_grab_focus(loginentry);
+
+ rootwin=gdk_window_foreign_new (GDK_ROOT_WINDOW ());
+
+ if(GdmDisplayBrowser) {
+ gtk_widget_show_all(GTK_WIDGET(browser));
+
+ gtk_widget_set_usize(GTK_WIDGET (greeter),
+ (gint) gdk_screen_width() * 0.6,
+ (gint) gdk_screen_height() * 0.8);
+ }
+
+ gtk_window_position(GTK_WINDOW (greeter), GTK_WIN_POS_CENTER);
+ gtk_widget_show_all(greeter);
+
+ hup.sa_handler = (void *) gdm_greeter_done;
+ hup.sa_flags = 0;
+ sigemptyset(&hup.sa_mask);
+
+ if(sigaction(SIGHUP, &hup, NULL) < 0)
+ gdm_greeter_abort(_("main: Error setting up HUP signal handler"));
+
+ if(sigaction(SIGINT, &hup, NULL) < 0)
+ gdm_greeter_abort(_("main: Error setting up INT signal handler"));
+
+ if(sigaction(SIGTERM, &hup, NULL) < 0)
+ gdm_greeter_abort(_("main: Error setting up TERM signal handler"));
+
+ usr1.sa_handler = (void *) gdm_greeter_invalid_passwd_req;
+ usr1.sa_flags = SA_RESTART;
+ sigemptyset(&usr1.sa_mask);
+ sigaddset(&usr2.sa_mask, SIGUSR2);
+
+ if(sigaction(SIGUSR1, &usr1, NULL) < 0)
+ gdm_greeter_abort(_("main: Error setting up USR1 signal handler"));
+
+ usr2.sa_handler = (void *) gdm_greeter_sesslang_send;
+ usr2.sa_flags = SA_RESTART;
+ sigemptyset(&usr2.sa_mask);
+ sigaddset(&usr2.sa_mask, SIGUSR1);
+
+ if(sigaction(SIGUSR2, &usr2, NULL) < 0)
+ gdm_greeter_abort(_("main: Error setting up USR2 signal handler"));
+
+ sigfillset(&mask);
+ sigdelset(&mask, SIGUSR1);
+ sigdelset(&mask, SIGUSR2);
+ sigdelset(&mask, SIGTERM);
+ sigdelset(&mask, SIGHUP);
+ sigdelset(&mask, SIGINT);
+
+ if(sigprocmask(SIG_SETMASK, &mask, NULL) == -1) {
+ syslog(LOG_ERR, "Could not set signal mask!");
+ exit(EXIT_FAILURE);
+ }
+
+ gtk_main();
+
+ return 0;
+}
+
+/* EOF */
diff --git a/gui/gdmgreeter.h b/gui/gdmgreeter.h
new file mode 100644
index 00000000..521b0f0e
--- /dev/null
+++ b/gui/gdmgreeter.h
@@ -0,0 +1,35 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __GDM_GREETER_H__
+#define __GDM_GREETER_H__
+
+#include <gnome.h>
+
+typedef struct _gdmUserType gdmUserType;
+
+struct _gdmUserType {
+ uid_t uid;
+ gchar *login;
+ gchar *homedir;
+ GdkImlibImage *picture;
+};
+
+#endif /* __GDM_GREETER_H__ */
+
+/* EOF */
diff --git a/gui/gdmlogin.c b/gui/gdmlogin.c
new file mode 100644
index 00000000..82fb5967
--- /dev/null
+++ b/gui/gdmlogin.c
@@ -0,0 +1,1133 @@
+/* GDM - The Gnome Display Manager
+ * Copyright (C) 1998, 1999 Martin Kasper Petersen <mkp@SunSITE.auc.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* gdmlogin is a stripped down greeter for environments where:
+ *
+ * 1. Users are not trusted (i.e. gdmlogin is less vulnerable to DoS
+ * attacks )
+ *
+ * 2. Usernames should not be exposed
+ */
+
+#include <config.h>
+#include <gnome.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <signal.h>
+#include <dirent.h>
+#include <gdk/gdkx.h>
+#include <pwd.h>
+
+#include "gdm.h"
+
+static const gchar RCSid[]="$Id$";
+
+extern gboolean gdm_file_check(gchar *caller, uid_t user, gchar *dir, gchar *file, gboolean absentok);
+
+gint GdmDebug;
+gint GdmIconify;
+gint GdmShutdownMenu;
+gint GdmVerboseAuth;
+gint GdmQuiver;
+gint GdmChooserMenu;
+gint GdmRelaxPerms;
+gint GdmUserMaxFile;
+gchar *GdmLogoFilename;
+gchar *GdmMessageText;
+gchar *GdmMessageFont;
+gchar *GdmConfigFilename=GDM_CONFIG_FILE;
+gchar *GdmMessageFont;
+gchar *GdmGtkRC;
+gchar *GdmIconFile;
+gchar *GdmSessionDir;
+gchar *GdmLocaleFile;
+gchar *GdmDefaultLocale;
+
+GtkWidget *login;
+GtkWidget *label;
+GtkWidget *entry;
+GtkWidget *msg;
+GtkWidget *win;
+GtkWidget *sessmenu;
+GtkWidget *langmenu;
+GdkWindow *rootwin;
+
+/* Eew. Loads of global vars. It's hard to be event controlled while maintaining state */
+GSList *sessions=NULL;
+GSList *languages=NULL;
+
+gchar *defsess=NULL;
+gchar *cursess=NULL;
+gchar *curlang=NULL;
+gchar *curuser=NULL;
+gchar *lastsess=NULL;
+gchar *lastlang=NULL;
+gchar *session=NULL;
+gchar *language=NULL;
+
+gboolean savesess;
+gboolean savelang;
+
+
+/* Log debug messages */
+void
+static gdm_debug(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ if(GdmDebug) {
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_DEBUG, s);
+
+ g_free(s);
+ }
+}
+
+
+static void
+gdm_login_done(void)
+{
+ closelog();
+ gtk_main_quit();
+ exit(DISPLAY_SUCCESS);
+}
+
+
+typedef struct _cursoroffset {gint x,y;} CursorOffset;
+
+
+static void
+gdm_login_icon_pressed(GtkWidget *widget, GdkEventButton *event)
+{
+ CursorOffset *p;
+
+ if(event->type == GDK_2BUTTON_PRESS) {
+ gtk_widget_destroy(win);
+ gdk_window_show(login->window);
+ return;
+ }
+
+ if (event->type != GDK_BUTTON_PRESS)
+ return;
+
+ p=gtk_object_get_user_data(GTK_OBJECT (widget));
+ p->x=(gint)event->x;
+ p->y=(gint)event->y;
+
+ gtk_grab_add(widget);
+ gdk_pointer_grab(widget->window, TRUE,
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK,
+ NULL, NULL, 0);
+}
+
+
+static void
+gdm_login_icon_released(GtkWidget *widget)
+{
+ gtk_grab_remove(widget);
+ gdk_pointer_ungrab(0);
+}
+
+
+static void
+gdm_login_icon_motion(GtkWidget *widget, GdkEventMotion *event)
+{
+ gint xp, yp;
+ CursorOffset *p;
+ GdkModifierType mask;
+
+ p=gtk_object_get_user_data(GTK_OBJECT (widget));
+ gdk_window_get_pointer(rootwin, &xp, &yp, &mask);
+ gtk_widget_set_uposition(widget, xp-p->x, yp-p->y);
+}
+
+
+static gboolean
+gdm_login_iconify_handler(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *fixed;
+ GtkWidget *icon;
+ GdkGC *gc;
+ GtkStyle *style;
+ CursorOffset *icon_pos;
+ gint rw, rh, iw, ih;
+
+ gdk_window_hide(login->window);
+ style=gtk_widget_get_default_style();
+ gc=style->black_gc;
+ win=gtk_window_new(GTK_WINDOW_POPUP);
+
+ gtk_widget_set_events(win,
+ gtk_widget_get_events(win) |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK);
+
+ gtk_widget_realize(win);
+
+ fixed=gtk_fixed_new();
+ gtk_container_add(GTK_CONTAINER (win), fixed);
+ gtk_widget_show(fixed);
+
+ icon=gnome_pixmap_new_from_file (GdmIconFile);
+ gdk_window_get_size ((GdkWindow *) GNOME_PIXMAP (icon)->pixmap, &iw, &ih);
+
+ gtk_fixed_put(GTK_FIXED (fixed), icon, 0, 0);
+ gtk_widget_show(icon);
+
+ gtk_signal_connect(GTK_OBJECT (win), "button_press_event",
+ GTK_SIGNAL_FUNC (gdm_login_icon_pressed),NULL);
+ gtk_signal_connect(GTK_OBJECT (win), "button_release_event",
+ GTK_SIGNAL_FUNC (gdm_login_icon_released),NULL);
+ gtk_signal_connect(GTK_OBJECT (win), "motion_notify_event",
+ GTK_SIGNAL_FUNC (gdm_login_icon_motion),NULL);
+
+ icon_pos=g_new(CursorOffset, 1);
+ gtk_object_set_user_data(GTK_OBJECT(win), icon_pos);
+
+ gtk_widget_show(win);
+
+ rw=gdk_screen_width();
+ rh=gdk_screen_height();
+
+ gtk_widget_set_uposition(win, rw-iw, rh-ih);
+
+ return(TRUE);
+}
+
+
+static void
+gdm_login_abort(const gchar *format, ...)
+{
+ va_list args;
+ gchar *s;
+
+ va_start(args, format);
+ s=g_strdup_vprintf(format, args);
+ va_end(args);
+
+ syslog(LOG_ERR, s);
+ closelog();
+ exit(DISPLAY_ABORT);
+}
+
+
+static gchar *
+gdm_parse_enriched_string(gchar *s)
+{
+ gchar cmd, *buffer, *start;
+ gchar hostbuf[256];
+ gchar *hostname, *temp1, *temp2, *display;
+
+ display=getenv("DISPLAY");
+
+ if(!display)
+ return(NULL);
+
+ temp1=strchr(display, '.');
+ temp2=strchr(display, ':');
+
+ if(temp1)
+ *temp1='\0';
+ else if(temp2)
+ *temp2='\0';
+ else
+ return(NULL); /* Display isn't */
+
+ gethostname(hostbuf, 255);
+ hostname=g_strdup(hostbuf);
+
+ if(!hostname)
+ hostname=g_strdup("Gnome");
+
+ if(strlen(s) > 1023) {
+ syslog(LOG_ERR, _("gdm_parse_enriched_string: String too long!"));
+ return(g_strconcat(_("Welcome to "), hostname, NULL));
+ }
+
+ if(!(buffer = g_malloc(4096))) {
+ syslog(LOG_ERR, _("gdm_parse_enriched_string: Could not malloc temporary buffer!"));
+ return(NULL);
+ }
+
+ start = buffer;
+
+ while(*s) {
+
+ if(*s=='%' && (cmd = s[1]) != 0) {
+ s+=2;
+
+ switch(cmd) {
+
+ case 'h':
+ memcpy(buffer, hostname, strlen(hostname));
+ buffer+=strlen(hostname);
+ break;
+
+ case 'd':
+ memcpy(buffer, display, strlen(display));
+ buffer+=strlen(display);
+ break;
+
+ case '%':
+ *buffer++='%';
+ break;
+
+ default:
+ break;
+ };
+ }
+ else
+ *buffer++=*s++;
+ }
+
+ *buffer=0;
+
+ return(g_strdup(start));
+}
+
+
+static void
+gdm_login_about(void)
+{
+ const gchar *authors[]={"Martin Kasper Petersen <mkp@mkp.net>", NULL};
+
+ GtkWidget *about;
+
+ about=gnome_about_new("Gnome Display Manager",
+ "" VERSION "",
+ "Copyright Martin K. Petersen (C) 1998, 1999",
+ authors,
+ _("gdm manages local and remote displays and provides the user with a login window."),
+ NULL);
+
+ gtk_widget_show(about);
+}
+
+
+static gboolean
+gdm_login_query(gchar *msg)
+{
+ GtkWidget *req;
+
+ req=gnome_message_box_new(msg,
+ GNOME_MESSAGE_BOX_QUESTION,
+ GNOME_STOCK_BUTTON_YES,
+ GNOME_STOCK_BUTTON_NO,
+ NULL);
+
+ gtk_window_set_modal(GTK_WINDOW(req), TRUE);
+ gtk_window_set_position(GTK_WINDOW(req), GTK_WIN_POS_CENTER);
+
+ return(!gnome_dialog_run(GNOME_DIALOG(req)));
+}
+
+
+static gboolean
+gdm_login_reboot_handler(void)
+{
+ if(gdm_login_query(_("Are you sure you want to reboot the machine?"))) {
+ closelog();
+ exit(DISPLAY_REBOOT);
+ }
+
+ return(TRUE);
+}
+
+
+static gboolean
+gdm_login_halt_handler(void)
+{
+ if(gdm_login_query(_("Are you sure you want to halt the machine?"))) {
+ closelog();
+ exit(DISPLAY_HALT);
+ }
+
+ return(TRUE);
+}
+
+
+static void
+gdm_login_parse_config(void)
+{
+ gchar *display;
+ struct stat unused;
+
+ if(stat(GDM_CONFIG_FILE, &unused) == -1)
+ gdm_login_abort(_("gdm_login_parse_config: No configuration file: %s. Aborting."), GDM_CONFIG_FILE);
+
+ gnome_config_push_prefix ("=" GDM_CONFIG_FILE "=/");
+
+ GdmLogoFilename=gnome_config_get_string("appearance/logoimage");
+ GdmMessageFont=gnome_config_get_string("appearance/msgfont=-adobe-helvetica-bold-r-normal-*-*-180-*-*-*-*-*-*");
+ GdmGtkRC=gnome_config_get_string("appearance/gtkrc");
+ GdmIconify=gnome_config_get_int("appearance/iconify=1");
+ GdmIconFile=gnome_config_get_string("appearance/iconfile=gdm.xpm");
+ GdmQuiver=gnome_config_get_int("appearance/quiver=1");
+
+ GdmChooserMenu=gnome_config_get_int("system/choosermenu=0");
+ GdmShutdownMenu=gnome_config_get_int("system/shutdownmenu=0");
+ GdmUserMaxFile=gnome_config_get_int("system/UserFileCutoffSize=65536");
+ GdmRelaxPerms=gnome_config_get_int("system/relaxpermissions=0");
+
+ GdmLocaleFile=g_strdup(gnome_config_get_string("system/LocaleFile"));
+ GdmDefaultLocale=g_strdup(gnome_config_get_string("system/DefaultLocale=english"));
+ GdmSessionDir=gnome_config_get_string("daemon/sessiondir");
+
+ GdmMessageText=gnome_config_get_string(_("messages/welcome=Welcome to %h"));
+
+ GdmDebug=gnome_config_get_int("debug/enable=0");
+
+ gnome_config_pop_prefix ();
+
+ if(stat(GdmLocaleFile, &unused) == -1)
+ gdm_login_abort("gdm_login_parse_config: Could not open locale file %s. Aborting!", GdmLocaleFile);
+
+ /* Disable System menu on non-local displays */
+ display=getenv("DISPLAY");
+
+ if(!display)
+ gdm_login_abort("gdm_login_parse_config: DISPLAY variable not set!");
+
+ if(strncmp(display, ":", 1))
+ GdmShutdownMenu=0;
+}
+
+
+static gboolean
+gdm_login_list_lookup(GSList *l, gchar *data)
+{
+ GSList *list=l;
+
+ if(!list || !data)
+ return(FALSE);
+
+ while(list) {
+
+ if(!strcasecmp(list->data, data))
+ return(TRUE);
+
+ list=list->next;
+ }
+
+ return(FALSE);
+}
+
+
+static void
+gdm_login_sesslang_lookup(void) /* Input validation sucks */
+{
+ struct passwd *pwent;
+ gboolean fileok;
+ gchar msg[1024];
+ gchar *dir=NULL, *cfg=NULL;
+ gchar *usrlang=NULL, *usrsess=NULL;
+
+ gtk_widget_set_sensitive(sessmenu, FALSE);
+ gtk_widget_set_sensitive(langmenu, FALSE);
+
+ /* Lookup verified user */
+ pwent=getpwnam(curuser);
+
+ dir=g_strconcat(pwent->pw_dir, "/.gnome", NULL);
+ fileok=gdm_file_check("gdm_login_sesslang_lookup", pwent->pw_uid, dir, "gdm", TRUE);
+ g_free(dir);
+
+ if(!fileok) { /* User's settings can't be retrieved */
+
+ /* If cursess==last use system default session */
+ if(!strcasecmp(cursess, lastsess))
+ session=defsess;
+ else
+ session=cursess;
+
+ /* If curlang==last use default */
+ if(!strcasecmp(curlang, lastlang))
+ language=GdmDefaultLocale;
+ else
+ language=curlang;
+
+ savesess=FALSE;
+ savelang=FALSE;
+
+ return;
+ }
+
+ /* Find user's last session and language if available */
+ cfg=g_strconcat("=", pwent->pw_dir, "/.gnome/gdm=/session/last", NULL);
+ usrsess=gnome_config_get_string(cfg);
+ g_free(cfg);
+
+ cfg=g_strconcat("=", pwent->pw_dir, "/.gnome/gdm=/session/lang", NULL);
+ usrlang=gnome_config_get_string(cfg);
+ g_free(cfg);
+
+ /* If ``Last'' session is selected */
+ if(!strcasecmp(cursess, lastsess)) {
+
+ /* User has no saved session. Use default. */
+ if(!usrsess) {
+ session=defsess;
+ savesess=TRUE;
+ }
+ /* User's saved session exists on this box */
+ else if(gdm_login_list_lookup(sessions, usrsess)) {
+ session=usrsess;
+ savesess=FALSE;
+ }
+ /* User's saved session type unknown */
+ else {
+ session=defsess;
+ g_snprintf(msg, 1023,
+ _("Your preferred session type %s is not installed on this machine.\n" \
+ "Do you wish to make %s the default for future sessions?"),
+ usrsess, defsess);
+ savesess=gdm_login_query(msg);
+ }
+ }
+ /* One of the other available session types is selected */
+ else {
+ session=cursess;
+
+ /* User has no saved session type. Use current */
+ if(!usrsess)
+ savesess=TRUE;
+ /* User's saved session is also the chosen one */
+ else if(!strcasecmp(usrsess, cursess))
+ savesess=FALSE;
+ /* User selected a new session type */
+ else {
+ g_snprintf(msg, 1023,
+ _("You have chosen %s for this session, but your default setting is %s.\n" \
+ "Do you wish to make %s the default for future sessions?"),
+ cursess, usrsess, cursess);
+ savesess=gdm_login_query(msg);
+ }
+ }
+
+ /* If ``Last'' language is selected */
+ if(!strcasecmp(curlang, lastlang)) {
+
+ /* User has no saved language. Use default. */
+ if(!usrlang) {
+ language=GdmDefaultLocale;
+ savelang=TRUE;
+ }
+ else {
+ language=usrlang;
+ savelang=FALSE;
+ }
+ }
+ /* One of the available languages is selected */
+ else {
+ language=curlang;
+
+ /* User has no saved language. Use current */
+ if(!usrlang)
+ savelang=TRUE;
+ /* User selected a new language */
+ else {
+ g_snprintf(msg, 1023,
+ _("You have chosen %s for this session, but your default setting is %s.\n" \
+ "Do you wish to make %s the default for future sessions?"),
+ curlang, usrlang, curlang);
+ savelang=gdm_login_query(msg);
+ }
+ }
+
+ return;
+}
+
+
+static gboolean
+gdm_login_entry_handler (GtkWidget *widget, GdkEventKey *event)
+{
+ if(!event)
+ return(TRUE);
+
+ switch(event->keyval) {
+
+ case GDK_Return:
+ gtk_widget_set_sensitive(entry, FALSE);
+
+ /* Save login. I'm making the assumption that login is always
+ * the first thing entered. This might not be true for all PAM
+ * setups. Needs thinking!
+ */
+
+ if(!curuser)
+ curuser=g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+
+ g_print("%s\n", gtk_entry_get_text(GTK_ENTRY(entry)));
+ break;
+
+ case GDK_Up:
+ case GDK_Down:
+ case GDK_Tab:
+ gtk_signal_emit_stop_by_name(GTK_OBJECT(entry), "key_press_event");
+ break;
+
+ break;
+
+ case GDK_F1:
+ gdm_login_about();
+ break;
+
+ default:
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+static void
+gdm_login_session_handler (GtkWidget *widget)
+{
+ gchar *s;
+
+ gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &cursess);
+ s=g_strdup_printf(_("%s session selected"), cursess);
+ gtk_label_set(GTK_LABEL(msg), s);
+ g_free(s);
+}
+
+
+static void
+gdm_login_session_init(GtkWidget *menu)
+{
+ GSList *sessgrp=NULL;
+ GtkWidget *item;
+ DIR *sessdir;
+ struct dirent *dent;
+ struct stat statbuf;
+ gint linklen;
+
+ lastsess=_("Last");
+
+ cursess=lastsess;
+ item = gtk_radio_menu_item_new_with_label(NULL, lastsess);
+ sessgrp = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(item));
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_signal_connect(GTK_OBJECT(item), "activate", gdm_login_session_handler, NULL);
+ gtk_widget_show(item);
+
+ item = gtk_menu_item_new();
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ /* Check that session dir is readable */
+ if (access(GdmSessionDir, R_OK|X_OK))
+ gdm_login_abort(_("gdm_login_session_init: Session script directory not found!"));
+
+ /* Read directory entries in session dir */
+ sessdir=opendir(GdmSessionDir);
+ dent=readdir(sessdir);
+
+ while(dent != NULL) {
+ gchar *s;
+
+ s=g_strconcat(GdmSessionDir, "/", dent->d_name, NULL);
+ lstat(s, &statbuf);
+
+ /* If default session link exists, find out what it points to */
+ if(S_ISLNK(statbuf.st_mode) && !strcasecmp(dent->d_name, "default")) {
+ gchar t[_POSIX_PATH_MAX];
+
+ linklen=readlink(s, t, _POSIX_PATH_MAX);
+ t[linklen]=0;
+ defsess=g_strdup(t);
+ }
+
+ /* If session script is readable/executable add it to the list */
+ if(S_ISREG(statbuf.st_mode)) {
+
+ if((statbuf.st_mode & (S_IRUSR|S_IXUSR)) == (S_IRUSR|S_IXUSR) &&
+ (statbuf.st_mode & (S_IRGRP|S_IXGRP)) == (S_IRGRP|S_IXGRP) &&
+ (statbuf.st_mode & (S_IROTH|S_IXOTH)) == (S_IROTH|S_IXOTH))
+ {
+ item=gtk_radio_menu_item_new_with_label(sessgrp, dent->d_name);
+ sessgrp=gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM (item));
+ sessions=g_slist_append(sessions, dent->d_name);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_signal_connect(GTK_OBJECT (item), "activate",
+ GTK_SIGNAL_FUNC (gdm_login_session_handler), NULL);
+ gtk_widget_show(item);
+ }
+ else
+ syslog(LOG_ERR, "Wrong permissions on %s/%s. Should be readable/executable for all.",
+ GdmSessionDir, dent->d_name);
+
+ }
+
+ dent=readdir(sessdir);
+ g_free(s);
+ }
+
+ if(!g_slist_length(sessgrp))
+ gdm_login_abort(_("No session scripts found. Aborting!"));
+
+ if(!defsess) {
+ gtk_label_get(GTK_LABEL(GTK_BIN(g_slist_nth_data(sessgrp, 0))->child), &defsess);
+ syslog(LOG_WARNING, _("No default session link found. Using %s.\n"), defsess);
+ }
+}
+
+
+static void
+gdm_login_language_handler (GtkWidget *widget)
+{
+ gchar *s;
+
+ gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &curlang);
+ s=g_strdup_printf(_("%s language selected"), curlang);
+ gtk_label_set(GTK_LABEL(msg), s);
+ g_free(s);
+}
+
+
+static void
+gdm_login_language_init(GtkWidget *menu)
+{
+ GtkWidget *item, *ammenu, *nzmenu, *omenu;
+ FILE *langlist;
+ char curline[256];
+ char *ctmp, *ctmp1, *ctmp2;
+
+ lastlang=_("Last");
+ curlang=lastlang;
+
+ item=gtk_radio_menu_item_new_with_label(NULL, lastlang);
+ languages=gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(item));
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_signal_connect(GTK_OBJECT(item), "activate", gdm_login_language_handler, NULL);
+ gtk_widget_show(item);
+
+ item=gtk_menu_item_new();
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ item=gtk_menu_item_new_with_label(_("A-M"));
+ ammenu=gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), ammenu);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ item=gtk_menu_item_new_with_label(_("N-Z"));
+ nzmenu=gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), nzmenu);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ item=gtk_menu_item_new_with_label(_("Other"));
+ omenu=gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), omenu);
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_widget_show(item);
+
+ langlist = fopen(GdmLocaleFile, "r");
+
+ if(!langlist)
+ return;
+
+ while(fgets(curline, sizeof(curline), langlist)) {
+
+ if(!isalpha(curline[0]))
+ continue;
+
+ ctmp1 = strchr(curline, ' ');
+ ctmp2 = strchr(curline, '\t');
+ ctmp = curline + strlen(curline) - 1;
+
+ if(ctmp1 && (ctmp1 < ctmp))
+ ctmp = ctmp1;
+
+ if(ctmp2 && (ctmp2 < ctmp))
+ ctmp = ctmp2;
+
+ *ctmp = '\0';
+ curline[0] = toupper(curline[0]);
+
+ item=gtk_radio_menu_item_new_with_label(languages, curline);
+ languages=gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(item));
+
+ if(curline[0] >= 'A' && curline[0] <= 'M')
+ gtk_menu_append(GTK_MENU(ammenu), item);
+ else if(curline[0] >= 'N' && curline[0] <= 'Z')
+ gtk_menu_append(GTK_MENU(nzmenu), item);
+ else
+ gtk_menu_append(GTK_MENU(omenu), item);
+
+ gtk_signal_connect(GTK_OBJECT(item), "activate", gdm_login_language_handler, NULL);
+ gtk_widget_show(item);
+ }
+
+ fclose(langlist);
+}
+
+
+static gboolean
+gdm_login_ctrl_handler(GIOChannel *source, GIOCondition cond, gint fd)
+{
+ gchar buf[PIPE_SIZE];
+ gint len;
+ gint i, x, y;
+
+ if(cond != G_IO_IN)
+ return(TRUE);
+
+ g_io_channel_read(source, buf, 1, &len);
+
+ if(len!=1)
+ return(TRUE);
+
+ switch(buf[0]) {
+ case GDM_PROMPT:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len);
+ buf[len-1]='\0';
+ gtk_label_set(GTK_LABEL(label), buf);
+ gtk_widget_show(label);
+ gtk_entry_set_text(GTK_ENTRY(entry), "");
+ gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
+ gtk_widget_set_sensitive(entry, TRUE);
+ gtk_widget_grab_focus(entry);
+ gtk_widget_show(entry);
+ break;
+
+ case GDM_NOECHO:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len);
+ buf[len-1]='\0';
+ gtk_label_set(GTK_LABEL(label), buf);
+ gtk_widget_show(label);
+ gtk_entry_set_text(GTK_ENTRY(entry), "");
+ gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
+ gtk_widget_set_sensitive(entry, TRUE);
+ gtk_widget_grab_focus(entry);
+ gtk_widget_show(entry);
+ break;
+
+ case GDM_MSGERR:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len);
+ buf[len-1]='\0';
+ gtk_label_set(GTK_LABEL(msg), buf);
+ gtk_widget_show(msg);
+ g_print("\n");
+ break;
+
+ case GDM_SESS:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len); /* Empty */
+ gdm_login_sesslang_lookup(); /* Lookup session and language */
+ g_print("%s\n", session);
+ break;
+
+ case GDM_LANG:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len); /* Empty */
+ g_print("%s\n", language);
+ break;
+
+ case GDM_SSESS:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len); /* Empty */
+
+ if(savesess)
+ g_print("Y\n");
+ else
+ g_print("\n");
+
+ break;
+
+ case GDM_SLANG:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len); /* Empty */
+
+ if(savelang)
+ g_print("Y\n");
+ else
+ g_print("\n");
+
+ break;
+
+ case GDM_RESET:
+ g_io_channel_read(source, buf, PIPE_SIZE-1, &len);
+ buf[len-1]='\0';
+
+ if(GdmQuiver) {
+ gdk_window_get_position(login->window, &x, &y);
+
+ for (i=32 ; i > 0 ; i=i/2) {
+ gdk_window_move(login->window, i+x, y);
+ gdk_window_move(login->window, x, y);
+ gdk_window_move(login->window, -i+x, y);
+ gdk_window_move(login->window, x, y);
+ }
+ }
+
+ if(curuser) {
+ g_free(curuser);
+ curuser=NULL;
+ }
+
+ g_print("\n");
+ break;
+
+ case GDM_QUIT:
+ exit(EXIT_SUCCESS);
+ break;
+
+ default:
+ break;
+ }
+
+ return(TRUE);
+}
+
+
+static void
+gdm_login_gui_init(void)
+{
+ GtkStyle *style;
+ GtkWidget *frame, *frame2, *hbox, *hline, *item, *lebox, *logo, *logobox;
+ GtkWidget *logoframe, *mbox, *menu, *menubar, *vbox, *welcome;
+ gchar *greeting;
+
+ if(GdmGtkRC)
+ gtk_rc_parse(GdmGtkRC);
+
+ rootwin=gdk_window_foreign_new (GDK_ROOT_WINDOW ());
+
+ login=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_container_border_width(GTK_CONTAINER(login), 0);
+
+ frame=gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
+ gtk_container_border_width(GTK_CONTAINER(frame), 0);
+ gtk_container_add(GTK_CONTAINER(login), frame);
+ gtk_widget_show(frame);
+
+ frame2=gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame2), GTK_SHADOW_IN);
+ gtk_container_border_width(GTK_CONTAINER(frame2), 2);
+ gtk_container_add(GTK_CONTAINER(frame), frame2);
+ gtk_widget_show(frame2);
+
+ mbox=gtk_vbox_new(FALSE,0);
+ gtk_container_add(GTK_CONTAINER(frame2), mbox);
+ gtk_widget_show(mbox);
+
+ menubar=gtk_menu_bar_new();
+ gtk_box_pack_start(GTK_BOX(mbox), menubar, FALSE, FALSE, 0);
+
+ menu=gtk_menu_new();
+ gdm_login_session_init(menu);
+ sessmenu=gtk_menu_item_new_with_label(_("Session"));
+ gtk_menu_bar_append(GTK_MENU_BAR(menubar), sessmenu);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(sessmenu), menu);
+ gtk_widget_show(sessmenu);
+
+ menu=gtk_menu_new();
+ gdm_login_language_init(menu);
+ langmenu=gtk_menu_item_new_with_label(_("Language"));
+ gtk_menu_bar_append(GTK_MENU_BAR(menubar), langmenu);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(langmenu), menu);
+ gtk_widget_show(langmenu);
+
+ if(GdmShutdownMenu) {
+ menu=gtk_menu_new();
+ item=gtk_menu_item_new_with_label(_("Reboot..."));
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_signal_connect(GTK_OBJECT (item), "activate",
+ GTK_SIGNAL_FUNC(gdm_login_reboot_handler), NULL);
+ gtk_widget_show(item);
+
+ item=gtk_menu_item_new_with_label(_("Halt..."));
+ gtk_menu_append(GTK_MENU(menu), item);
+ gtk_signal_connect(GTK_OBJECT(item), "activate",
+ GTK_SIGNAL_FUNC(gdm_login_halt_handler), NULL);
+ gtk_widget_show(item);
+
+ item=gtk_menu_item_new_with_label(_("System"));
+ gtk_menu_bar_append(GTK_MENU_BAR(menubar), item);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
+ gtk_widget_show(item);
+ }
+
+ if(GdmChooserMenu) {
+ item=gtk_menu_item_new_with_label(_("Host chooser"));
+ gtk_menu_bar_append(GTK_MENU_BAR(menubar), item);
+ gtk_widget_show(item);
+ }
+
+ if(GdmIconify) {
+ if(access(GdmIconFile, R_OK)) {
+ syslog(LOG_WARNING, _("Can't open icon file: %s. Suspending iconify feature!"), GdmIconFile);
+ GdmIconify=0;
+ }
+ else {
+ item=gtk_menu_item_new_with_label(_("Iconify"));
+ gtk_menu_bar_append(GTK_MENU_BAR(menubar), item);
+ gtk_signal_connect(GTK_OBJECT(item), "activate",
+ GTK_SIGNAL_FUNC(gdm_login_iconify_handler), NULL);
+ gtk_widget_show(item);
+ }
+ }
+
+ hbox=gtk_hbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(hbox), 10);
+ gtk_box_pack_end(GTK_BOX(mbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show(hbox);
+
+ if (GdmLogoFilename && !access(GdmLogoFilename, R_OK)) {
+ logobox=gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), logobox, FALSE, FALSE, 0);
+
+ logoframe=gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(logoframe), GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(logobox), logoframe, FALSE, FALSE, 0);
+ gtk_widget_show(logoframe);
+
+ logo=gnome_pixmap_new_from_file(GdmLogoFilename);
+ gtk_container_add(GTK_CONTAINER(logoframe), logo);
+ gtk_widget_show(logo);
+
+ gtk_widget_show(logobox);
+ }
+
+ vbox=gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 10);
+ gtk_widget_show(vbox);
+
+ style = gtk_style_new();
+ gdk_font_unref(style->font);
+ style->font = gdk_font_load (GdmMessageFont);
+ gtk_widget_push_style(style);
+ greeting=gdm_parse_enriched_string(GdmMessageText);
+ welcome=gtk_label_new(greeting);
+ g_free(greeting);
+ gtk_box_pack_start(GTK_BOX(vbox), welcome, TRUE, FALSE, 10);
+ gtk_widget_show(welcome);
+ gtk_widget_pop_style();
+
+ msg=gtk_label_new("Please enter your login");
+ gtk_box_pack_end(GTK_BOX(vbox), msg, FALSE, TRUE, 0);
+ gtk_widget_show(msg);
+
+ hline=gtk_hseparator_new();
+ gtk_box_pack_end(GTK_BOX(vbox), hline, FALSE, FALSE, 10);
+ gtk_widget_show(hline);
+
+ lebox=gtk_vbox_new(FALSE, 0);
+ gtk_container_border_width(GTK_CONTAINER(lebox), 5);
+ gtk_box_pack_end(GTK_BOX(vbox), lebox, FALSE, FALSE, 5);
+ gtk_widget_show(lebox);
+
+ label=gtk_label_new("Login:");
+ gtk_box_pack_start(GTK_BOX(lebox), label, FALSE, FALSE, 5);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+ gtk_widget_show(label);
+
+ entry=gtk_entry_new_with_max_length(32);
+ gtk_box_pack_start(GTK_BOX(lebox), entry, FALSE, FALSE, 5);
+ gtk_entry_set_text(GTK_ENTRY(entry), "");
+ gtk_signal_connect_object(GTK_OBJECT(entry),
+ "key_press_event",
+ GTK_SIGNAL_FUNC(gdm_login_entry_handler),
+ NULL);
+ gtk_widget_show(entry);
+
+ hline=gtk_hseparator_new();
+ gtk_box_pack_end(GTK_BOX(vbox), hline, FALSE, FALSE, 10);
+ gtk_widget_show(hline);
+
+ gtk_widget_grab_focus(entry);
+ gtk_window_set_focus(GTK_WINDOW (login), entry);
+ gtk_window_set_policy(GTK_WINDOW (login), 1, 1, 1);
+ gtk_window_position(GTK_WINDOW (login), GTK_WIN_POS_CENTER);
+
+ gtk_widget_set_usize(GTK_WIDGET(login),
+ (gint)gdk_screen_width() * 0.5,
+ 0);
+
+ gtk_widget_show_all(login);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ struct sigaction hup;
+ sigset_t mask;
+ GIOChannel *ctrlch;
+
+ /* Avoid creating ~gdm/.gnome stuff */
+ gnome_do_not_create_directories = TRUE;
+
+ openlog("gdmlogin", LOG_PID, LOG_DAEMON);
+
+ gnome_init("gdmlogin", VERSION, argc, argv);
+ gnome_sound_shutdown ();
+
+ gdm_login_parse_config();
+ gdm_login_gui_init();
+
+ hup.sa_handler = (void *) gdm_login_done;
+ hup.sa_flags = 0;
+ sigemptyset(&hup.sa_mask);
+
+ if(sigaction(SIGHUP, &hup, NULL) < 0)
+ gdm_login_abort(_("main: Error setting up HUP signal handler"));
+
+ if(sigaction(SIGINT, &hup, NULL) < 0)
+ gdm_login_abort(_("main: Error setting up INT signal handler"));
+
+ if(sigaction(SIGTERM, &hup, NULL) < 0)
+ gdm_login_abort(_("main: Error setting up TERM signal handler"));
+
+ sigfillset(&mask);
+ sigdelset(&mask, SIGTERM);
+ sigdelset(&mask, SIGHUP);
+ sigdelset(&mask, SIGINT);
+
+ if(sigprocmask(SIG_SETMASK, &mask, NULL) == -1) {
+ syslog(LOG_ERR, "Could not set signal mask!");
+ exit(EXIT_FAILURE);
+ }
+
+ ctrlch = g_io_channel_unix_new(STDIN_FILENO);
+ g_io_channel_init(ctrlch);
+ g_io_add_watch(ctrlch,
+ G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ (GIOFunc) gdm_login_ctrl_handler,
+ NULL);
+ g_io_channel_unref(ctrlch);
+
+ gtk_main();
+
+ exit(EXIT_SUCCESS);
+}
+
+/* EOF */
diff --git a/pixmaps/.cvsignore b/pixmaps/.cvsignore
new file mode 100644
index 00000000..282522db
--- /dev/null
+++ b/pixmaps/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am
new file mode 100644
index 00000000..f5ca7b8a
--- /dev/null
+++ b/pixmaps/Makefile.am
@@ -0,0 +1,8 @@
+pixmapdir = $(datadir)/pixmaps
+
+BITMAPS = gdm.xpm nophoto.png
+
+pixmap_DATA = $(BITMAPS)
+
+EXTRA_DIST = $(BITMAPS)
+
diff --git a/pixmaps/gdm.xpm b/pixmaps/gdm.xpm
new file mode 100644
index 00000000..201895f1
--- /dev/null
+++ b/pixmaps/gdm.xpm
@@ -0,0 +1,285 @@
+/* XPM */
+static char * image_name[] = {
+"48 48 234 2",
+" c #C71BCB2BC71B",
+". c #BEFBBEFBBEFB",
+"X c #BEFBBAEABEFB",
+"o c #B6DABAEABEFB",
+"O c #BEFBC30BC71B",
+"+ c #BEFBBEFBB6DA",
+"@ c #B6DAB6DAB6DA",
+"# c #C71BC71BC71B",
+"$ c #A699AEBAAEBA",
+"% c #EFBEF3CEF7DE",
+"& c #E79DEBADEFBE",
+"* c #CF3CD34CD75C",
+"= c #CF3CCF3CCF3C",
+"- c #D75CD75CD75C",
+"; c #D75CDB6CD75C",
+": c #DF7DDF7DD75C",
+"> c #DF7DE38DE79D",
+", c #D75CD75CCF3C",
+"< c #71C679E779E7",
+"1 c #514451445144",
+"2 c #A699AAAAAEBA",
+"3 c #A699AAAAA699",
+"4 c #9E79A699A699",
+"5 c #9E79A289A699",
+"6 c #9E799E79A699",
+"7 c #9E799E799E79",
+"8 c #96589A699E79",
+"9 c #965896589658",
+"0 c #8E3892489658",
+"q c #8E388E388E38",
+"w c #861786178617",
+"e c #79E782078617",
+"r c #86178A288617",
+"t c #96589A699658",
+"y c #514459655965",
+"u c #49244D344924",
+"i c #8E3892488E38",
+"p c #9E79A2899E79",
+"a c #410341034103",
+"s c #492449244924",
+"d c #38E33CF338E3",
+"f c #410345144103",
+"g c #86178A288E38",
+"h c #8E388E389E79",
+"j c #861786179E79",
+"k c #79E77DF779E7",
+"l c #8E3886178617",
+"z c #AEBAB2CAAEBA",
+"x c #AEBAB6DAB6DA",
+"c c #79E77DF78E38",
+"v c #71C675D671C6",
+"b c #86177DF779E7",
+"n c #69A675D671C6",
+"m c #69A671C671C6",
+"M c #B6DAB2CABEFB",
+"N c #EFBEEBADDF7D",
+"B c #E79DE79DDF7D",
+"V c #E79DE38DD75C",
+"C c #DF7DDB6CD75C",
+"Z c #DF7DDB6CCF3C",
+"A c #D75CD34CBEFB",
+"S c #D75CCF3CC71B",
+"D c #CF3CCF3CC71B",
+"F c #CF3CCB2BBEFB",
+"G c #CF3CC71BBEFB",
+"H c #C71BC71BBEFB",
+"J c #C71BC30BB6DA",
+"K c #C71BBEFBB6DA",
+"L c #BEFBBAEAB6DA",
+"P c #BEFBB6DAAEBA",
+"I c #B6DAAEBAA699",
+"U c #96588E388E38",
+"Y c #79E779E779E7",
+"T c #38E338E338E3",
+"R c #DF7DD75CCF3C",
+"E c #BEFBB2CAAEBA",
+"W c #AEBAA699A699",
+"Q c #A6999E799658",
+"! c #618561856185",
+"~ c #861779E779E7",
+"^ c #79E775D671C6",
+"/ c #69A669A679E7",
+"( c #69A66DB671C6",
+") c #618565956185",
+"_ c #5965596569A6",
+"` c #596555555144",
+"' c #5144555571C6",
+"] c #4924492469A6",
+"[ c #410345145965",
+"{ c #492445145144",
+"} c #96588A288E38",
+"| c #B6DAB2CAAEBA",
+" . c #8E388A288617",
+".. c #9E799A699658",
+"X. c #71C675D68617",
+"o. c #6185659579E7",
+"O. c #5144514471C6",
+"+. c #49244D3479E7",
+"@. c #4924492471C6",
+"#. c #965892488E38",
+"$. c #30C234D330C2",
+"%. c #51444D344924",
+"&. c #9E799E79B6DA",
+"*. c #71C671C69658",
+"=. c #71C671C68E38",
+"-. c #514455558617",
+";. c #492449249658",
+":. c #492449248617",
+">. c #492445148E38",
+",. c #410341036185",
+"<. c #208124922081",
+"1. c #492445144103",
+"2. c #79E779E79658",
+"3. c #AEBAAAAAB6DA",
+"4. c #71C675D69E79",
+"5. c #596559659658",
+"6. c #514455559658",
+"7. c #38E33CF39E79",
+"8. c #410345149658",
+"9. c #596559658617",
+"0. c #69A665956185",
+"q. c #38E33CF35144",
+"w. c #208120812081",
+"e. c #59655D755965",
+"r. c #69A66DB68E38",
+"t. c #618561858E38",
+"y. c #69A669A69E79",
+"u. c #410345149E79",
+"i. c #618565959658",
+"p. c #49244924A699",
+"a. c #59655965A699",
+"s. c #69A66DB6B6DA",
+"d. c #49244D34A699",
+"f. c #49244924B6DA",
+"g. c #38E338E38617",
+"h. c #A699A289B6DA",
+"j. c #30C234D34924",
+"k. c #30C230C238E3",
+"l. c #20811C711861",
+"z. c #514455555144",
+"x. c #618569A66185",
+"c. c #41034514B6DA",
+"v. c #51445144B6DA",
+"b. c #71C675D6AEBA",
+"n. c #8E388E38B6DA",
+"m. c #61856595AEBA",
+"M. c #59655D758E38",
+"N. c #38E33CF369A6",
+"B. c #30C230C25144",
+"V. c #30C230C230C2",
+"C. c #186118611861",
+"Z. c #28A22CB228A2",
+"A. c #86178207AEBA",
+"S. c #DF7DDB6CBEFB",
+"D. c #30C234D371C6",
+"F. c #186114511040",
+"G. c #28A228A228A2",
+"H. c #596561855965",
+"J. c #492451444924",
+"K. c #E79DDF7DD75C",
+"L. c #8E388E38A699",
+"P. c #38E334D379E7",
+"I. c #28A22CB26185",
+"U. c #28A22CB24103",
+"Y. c #28A228A25144",
+"T. c #AEBAB2CAB6DA",
+"R. c #51445555AEBA",
+"E. c #28A22CB28E38",
+"W. c #208124924924",
+"Q. c #38E33CF34924",
+"!. c #D75CD75CBEFB",
+"~. c #E79DE38DBEFB",
+"^. c #96589248AEBA",
+"/. c #28A228A271C6",
+"(. c #AEBAAEBAA699",
+"). c #69A66DB669A6",
+"_. c #59655D75A699",
+"`. c #208124928617",
+"'. c #28A22CB279E7",
+"]. c #208120814924",
+"[. c #8617820779E7",
+"{. c #618569A669A6",
+"}. c #79E779E7B6DA",
+"|. c #28A228A29658",
+" X c #30C230C28E38",
+".X c #30C234D38E38",
+"XX c #20811C718E38",
+"oX c #79E779E771C6",
+"OX c #5965596579E7",
+"+X c #71C671C6A699",
+"@X c #104014514103",
+"#X c #618561859E79",
+"$X c #30C234D39658",
+"%X c #186118616185",
+"&X c #186114515144",
+"*X c #1040104038E3",
+"=X c #79E771C671C6",
+"-X c #514455556185",
+";X c #38E338E379E7",
+":X c #30C230C269A6",
+">X c #2081208179E7",
+",X c #18611C7169A6",
+"<X c #10400C3028A2",
+"1X c #71C671C669A6",
+"2X c #104010401040",
+"3X c #49244D349658",
+"4X c #49244D3469A6",
+"5X c #18611C714924",
+"6X c #A699A2899E79",
+"7X c #69A669A66185",
+"8X c #AEBA79E769A6",
+"9X c #A6998A288617",
+"0X c #A6996DB669A6",
+"qX c #9E797DF769A6",
+"wX c #9E7979E769A6",
+"eX c #8E3896585965",
+"rX c #9658BAEA2081",
+"tX c #8E389A6938E3",
+"yX c #71C66DB669A6",
+"uX c #71C669A669A6",
+"iX c #514469A66185",
+"pX c #8E3886176185",
+"aX c #9E7996588E38",
+"sX c #861779E771C6",
+"dX c #596559655144",
+"fX c #410351445144",
+"gX c #082008200820",
+"hX c #082004100000",
+"jX c #10400C300820",
+"kX c #69A661855965",
+"lX c #69A669A669A6",
+"zX c #96588E388617",
+"xX c #DF7DDF7DDF7D",
+"cX c #514459655144",
+" . . . . . . X X o o . . . . O + . . + . . . . O O O O . o @ o @ @ @ o . O O # # # . @ X $ $ ",
+"o % & * * * * = * - - * * * - - - ; - - ; - - : > : : : ; ; , ; - - ; ; ; ; ; : : > : ; ; o < 1 ",
+"X : # $ 2 $ $ 3 4 5 4 5 4 4 2 2 2 2 2 2 $ $ $ 6 7 8 9 9 0 q w e r r q 0 8 7 5 4 6 8 q q 9 t y u ",
+"@ ; 4 0 9 9 9 0 i i q i 0 9 9 9 9 9 t t 8 9 0 9 9 0 q q q r e w r i i 0 9 7 p 8 i q q i p q a s ",
+"@ ; $ i 0 9 9 9 0 0 i q 0 0 i i 0 i 0 9 0 i q q i q q q r w e e r q q 9 t 8 9 q w r i 8 p r d f ",
+"@ , $ 9 i 0 9 0 9 0 q q q 0 q g q g h g g w j q q g w w w e k e l g q 0 9 t q w r 9 8 8 7 w d s ",
+"o ; z 9 i 9 9 i i h g w g g g w g r w w w w w g q r w e w k k e e w g i 0 g e e i 8 t t 7 w d u ",
+"x - $ 7 0 i q g g g e e e w r w w e k < k e w g w c k c < < < c e e w g g e < w h 9 9 9 7 q a u ",
+"x , 2 7 0 g g l w k v < k c b < v n n m v < < k k v n n m n n v v < c e c n n w w q 0 8 p i a s ",
+"M - 3 7 h e e e , N N N N N B B V V : : C Z ; , A S D F D G H J K + L P I 8 U Y < e q 7 $ q T a ",
+"x - 4 t q e b , N N N N N & B B V : > C R R ; A * * F F G H J K + L L E I W Q e ! n g 5 3 w T f ",
+"@ - 4 9 g e e N N X Y Y ~ v Y ^ v v / ( ) ) ! _ _ ` ' u ] ] ] [ { a f a a l Q } s ! e 0 8 k T u ",
+"| , 4 0 q w e N N Y .H ..9 .Y c c X./ o.o.o.' O.+.O.@.] ] ] { [ { { f a T ..#.$.%.m e r n $.s ",
+"@ * 5 g g w Y N N .@ V @ &.*./ o.o.=.' -.-.@.;.:.:.>.>.>.>.>.@.] ,.{ T T T ..9 <.f ! < l n $.1.",
+"@ - p r l r k N % ^ W # h 2.2.*.-.*.3.4.5.6.6.6.6.7.8.;.;.>.:.9.] 0.q.q.T $.9 i w.d e.< w m $.f ",
+"@ * 5 g q g Y N B 2.W @ r.t.y.6.u.>.i.p.>.p.a.a.s.a.p.d.f.g.8.8.t.h.' T j.k.9 } l.T z.( e x.$.s ",
+"@ * p q 0 q k B B < &.h 4.y.t.5.d.p.f.p.f.c.f.v.b.h.n.&.n.m.f.g.7.M.N.q.B.V.#. .C.Z.s ! n x.$.u ",
+"@ * 7 0 0 i c V B c j h i.5.p.p.p.p.f.f.f.f.f.f.s.A.h.S.# W A.d.g.g.D.B.B.k.i .F.G.f H.v m T J.",
+"x * 7 i 0 q k V K.j L.j A.m.d.a.f.c.p.y.f.f.c.f.f.f.v.&.# * F h.a.u.P.I.U.Y.} l F.G.a ! e k d J.",
+"T.= p 0 9 h v K.: y.2.y.5.d.p.u.f.f.s.M s.c.f.f.c.c.f.a.X A , 3.R.E.E.D.Y.W.U l F.G.f ) k < Q.s ",
+"$ 5 9 9 q v > : / i.d.5.p.p.p.f.c.R.s.f.f.c.f.f.c.f.c.X !.~.M ^.f.E./.I.Y.} l F.G.f ! < n T s ",
+"(.D 5 9 8 g ).C : *.*.d.a.d.d.c.p.f.f.c.f._.f.f.f.f.f.f.H ~.B M &.7.`.'.Y.]. .[.F.Z.1.! < ).$.f ",
+"T.= 5 9 i e {.C , 9.5.;.8.>._.p.p.f.f.f.v.s.v.f.f.f.f.}.!.A ~.H &.f.|.`.D.W.l b F.Z.1.! < m $.f ",
+"@ * 7 0 q e {.R ; M.9.p.u._.^._.f.p.c.f.c.v.f.c.c.c.f.^.~.A S.S n.7.`. Xj I.[.b F.G.f ! < m T f ",
+"+ - 8 0 g e n - A 9.9.>.d.p.a.u.f.p.f.f.f.v.f.f.f.c.n.R S.!.!.O A.7.|.d.X O.l ~ F.Z.f ! < ).$.1.",
+"O * 8 i w e m A A -.-.;.p.>.p.p.p.p.f.f.b.b.b.m.s.3.S.S.F !.G 3.f.|.|..Xj W.[.k F.G.s ! v m T f ",
+"O - t q w e v S * ' -.O.6.p.;.u.p.p.f.m.3.^.F O S S * F F H h.}.|.XX Xn.F O.b oXC.G.f ! < ).T f ",
+"O - 9 i e w < S F OXO.' -.i.>.>.;.p.>.f.A.}.G H !.S.~.A F h.+XR.|.XXXX'.O.@XoX^ F.Z.1.! v m $.s ",
+"O , 0 q w e < F F _ _ O.' 2.-.>.>.y.u.u.f.u.#X+X}.A.^.4.y.7.$X|.XXXX%X%X&X*XY =XF.Z.f ) < m $.s ",
+"# - 0 g w w < F F y -XO.O.' @.@.y.M y.>.7.7.7.g.P.P.;X:X/.>X,X>X,X%X%X&X*X<X=X1X2XG.f ! v m T f ",
+"# , 0 q g w c G H ` y -X-XO.-X_ O.4.;.:.3X;.;.;.+.:.O.@.' 4XO.+.+.:.:.4X4X<X=X=X2XG.a ! < ).T s ",
+"O ; i g g g k G J 9 u u u 1.,.u [ ,.N.N.;X:X:XI.Y.W.Y.W.].5X5X5X@X@X@X*X<X) ^ =X2X<.a ! < n T J.",
+"O , 0 g g w < | J o P P E | (.I I W W W 6X6 Q 6 ..#.9 9 U . .h r [.[.oX^ =X1X0.2X<.a e.k < T u ",
+" ; 0 q g w k 7X9 I I 2 2 W 6XQ Q 8X9X..U 0XqXi #.0XwXl } e m [.eXrXtX=XyXuXe.` 2X<.d ! Y n T s ",
+"# ; 9 i q g e ).y iXpX..Q ....aX9 #.#.U U .} l [.e [.[.~ sX^ oX1X1X0.0.dXfXfXgX2X<.d y m {.V.a ",
+"# ; 9 i q g e < ! 1 T Z.l.C.a a %.yXuX%.dX^ oXdX0.^ 1X` dXe.s %.hXhXgXgXjXgXjX2XC.G.d z.7X) k.f ",
+"H ; 8 9 i q w b ).! %.a k.G.%.s e.H.1 1 e.e.z.e.7XkXz.dXlXuXdXe.hXjX2X2XF.F.F.C.w.V.f e.n m T s ",
+"# ; 7 9 h q r w < ).H.b w zX} U . .l l [.l b b b oXv ^ ^ ^ 1XuX0.e.e.` l.w.w.G.$.f z.).k < $.s ",
+"# ; 8 9 q q q g e < x.q q ..#.9 #.#.U U .U l [.[.b [.b oXsX< 1XuXyX` dXG.Z.$.T 1.z.) v g k T s ",
+"O ; 7 9 0 U q i .k v x.z.f $.G.l.C.2XF.2X2X2X2X2X2XF.2XF.F.F.C.C.l.<.Z.$.d f u ` x.v w q k T s ",
+"O ; t 9 9 i q i q r b v e.u a T V.Z.<.<.<.<.w.<.<.<.G.G.G.<.G.G.Z.k.T a s 1 y ! lXn e q 9 e T u ",
+"# ; 9 t 9 9 i q 9 i q e m H.` u s f 1.a a a d d a a a 1.1.s 1.s s u 1 z.e.) ).n k w g i t e T s ",
+"# xX9 8 t 9 0 9 7 7 9 q e v m 7Xx.x.) ) ) 7X! ! ! ) ) ) 0.) ) 7X0.7X).).v < e r g i 0 9 8 w d u ",
+"O ; 7 8 9 0 9 7 5 5 7 9 q w k < oXk k k e w w k b k < < w w e e w e e w l q q 0 9 8 7 7 7 w d u ",
+"# xX8 9 9 i 9 4 3 4 5 9 i r r w w q q i i 8 9 i g g r g 9 9 q q 9 9 9 9 9 t 8 8 8 7 p 7 7 e T u ",
+" = t i i 9 p 3 4 5 t i q r r r q i 9 9 t 8 p 8 q i i i e e k k k k k k k c k e w w e e k m d s ",
+"+ &.cXV.$.$.T d d $.G.<.G.<.<.<.<.<.G.G.G.G.G.G.G.G.<.G.T $.$.j.T T $.$.$.T T T T $.$.$.$.Z.G.s ",
+"r -Xu a f u J.1 u u z.z.J.J.J.J.-XcXcXy y y e.cXz.z.cXcXcXe.e.cXcXcXcX-XcXcXcXy cXy cXe.cXz.1.e."};
diff --git a/pixmaps/nophoto.png b/pixmaps/nophoto.png
new file mode 100644
index 00000000..085fe26d
--- /dev/null
+++ b/pixmaps/nophoto.png
Binary files differ
diff --git a/po/.cvsignore b/po/.cvsignore
new file mode 100644
index 00000000..d66a1d6d
--- /dev/null
+++ b/po/.cvsignore
@@ -0,0 +1,9 @@
+*.gmo
+*.mo
+Makefile
+Makefile.in
+POTFILES
+cat-id-tbl.c
+gdm.pot
+stamp-cat-id
+
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 00000000..8bda9ab1
--- /dev/null
+++ b/po/ChangeLog
@@ -0,0 +1,4 @@
+1999-02-17 Kjartan Maraas <kmaraas@fib.hl.no>
+
+ * no.po: Updated
+
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
new file mode 100644
index 00000000..111b40fc
--- /dev/null
+++ b/po/Makefile.in.in
@@ -0,0 +1,248 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+#
+# This file file be copied and used freely without restrictions. It can
+# be used in projects which are not available under the GNU Public License
+# but which still want to provide support for the GNU gettext functionality.
+# Please note that the actual code is *not* freely available.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = $(prefix)/@DATADIRNAME@
+localedir = $(datadir)/locale
+gnulocaledir = $(prefix)/share/locale
+gettextsrcdir = $(prefix)/share/gettext/po
+subdir = po
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@
+
+CC = @CC@
+GENCAT = @GENCAT@
+GMSGFMT = PATH=../src:$$PATH @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = PATH=../src:$$PATH @XGETTEXT@
+MSGMERGE = PATH=../src:$$PATH msgmerge
+
+DEFS = @DEFS@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+
+INCLUDES = -I.. -I$(top_srcdir)/intl
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+SOURCES = cat-id-tbl.c
+POFILES = @POFILES@
+GMOFILES = @GMOFILES@
+DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \
+stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES)
+
+POTFILES = \
+
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+INSTOBJEXT = @INSTOBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat
+
+.c.o:
+ $(COMPILE) $<
+
+.po.pox:
+ $(MAKE) $(PACKAGE).pot
+ $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+.po.gmo:
+ file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \
+ && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+.po.cat:
+ sed -f ../intl/po2msg.sed < $< > $*.msg \
+ && rm -f $@ && $(GENCAT) $@ $*.msg
+
+
+all: all-@USE_NLS@
+
+all-yes: cat-id-tbl.c $(CATALOGS)
+all-no:
+
+$(srcdir)/$(PACKAGE).pot: $(POTFILES)
+ $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \
+ --add-comments --keyword=_ --keyword=N_ \
+ --files-from=$(srcdir)/POTFILES.in \
+ && test ! -f $(PACKAGE).po \
+ || ( rm -f $(srcdir)/$(PACKAGE).pot \
+ && mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot )
+
+$(srcdir)/cat-id-tbl.c: stamp-cat-id; @:
+$(srcdir)/stamp-cat-id: $(PACKAGE).pot
+ rm -f cat-id-tbl.tmp
+ sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \
+ | sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp
+ if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \
+ rm cat-id-tbl.tmp; \
+ else \
+ echo cat-id-tbl.c changed; \
+ rm -f $(srcdir)/cat-id-tbl.c; \
+ mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \
+ fi
+ cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id
+
+
+install: install-exec install-data
+install-exec:
+install-data: install-data-@USE_NLS@
+install-data-no: all
+install-data-yes: all
+ if test -r "$(MKINSTALLDIRS)"; then \
+ $(MKINSTALLDIRS) $(datadir); \
+ else \
+ $(SHELL) $(top_srcdir)/mkinstalldirs $(datadir); \
+ fi
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ case "$$cat" in \
+ *.gmo) destdir=$(gnulocaledir);; \
+ *) destdir=$(localedir);; \
+ esac; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ dir=$$destdir/$$lang/LC_MESSAGES; \
+ if test -r "$(MKINSTALLDIRS)"; then \
+ $(MKINSTALLDIRS) $$dir; \
+ else \
+ $(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \
+ fi; \
+ if test -r $$cat; then \
+ $(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+ echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+ else \
+ $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
+ echo "installing $(srcdir)/$$cat as" \
+ "$$dir/$(PACKAGE)$(INSTOBJEXT)"; \
+ fi; \
+ if test -r $$cat.m; then \
+ $(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+ echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+ else \
+ if test -r $(srcdir)/$$cat.m ; then \
+ $(INSTALL_DATA) $(srcdir)/$$cat.m \
+ $$dir/$(PACKAGE)$(INSTOBJEXT).m; \
+ echo "installing $(srcdir)/$$cat as" \
+ "$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \
+ else \
+ true; \
+ fi; \
+ fi; \
+ done
+ if test "$(PACKAGE)" = "gettext"; then \
+ if test -r "$(MKINSTALLDIRS)"; then \
+ $(MKINSTALLDIRS) $(gettextsrcdir); \
+ else \
+ $(SHELL) $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \
+ fi; \
+ $(INSTALL_DATA) $(srcdir)/Makefile.in.in \
+ $(gettextsrcdir)/Makefile.in.in; \
+ else \
+ : ; \
+ fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+ catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+ rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+ rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \
+ rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \
+ done
+ rm -f $(gettextsrcdir)/po-Makefile.in.in
+
+check: all
+
+cat-id-tbl.o: ../intl/libgettext.h
+
+dvi info tags TAGS ID:
+
+mostlyclean:
+ rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp
+ rm -fr *.o
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f $(GMOFILES)
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: update-po $(DISTFILES)
+ dists="$(DISTFILES)"; \
+ for file in $$dists; do \
+ ln $(srcdir)/$$file $(distdir) 2> /dev/null \
+ || cp -p $(srcdir)/$$file $(distdir); \
+ done
+
+update-po: Makefile
+ $(MAKE) $(PACKAGE).pot
+ PATH=`pwd`/../src:$$PATH; \
+ cd $(srcdir); \
+ catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \
+ mv $$lang.po $$lang.old.po; \
+ echo "$$lang:"; \
+ if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \
+ rm -f $$lang.old.po; \
+ else \
+ echo "msgmerge for $$cat failed!"; \
+ rm -f $$lang.po; \
+ mv $$lang.old.po $$lang.po; \
+ fi; \
+ done
+
+POTFILES: POTFILES.in
+ ( if test 'x$(srcdir)' != 'x.'; then \
+ posrcprefix='$(top_srcdir)/'; \
+ else \
+ posrcprefix="../"; \
+ fi; \
+ rm -f $@-t $@ \
+ && (sed -e '/^#/d' -e '/^[ ]*$$/d' \
+ -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
+ | sed -e '$$s/\\$$//') > $@-t \
+ && chmod a-w $@-t \
+ && mv $@-t $@ )
+
+Makefile: Makefile.in.in ../config.status POTFILES
+ cd .. \
+ && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
+ $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 00000000..cf5a1857
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,11 @@
+daemon/gdm.c
+daemon/auth.c
+daemon/filecheck.c
+daemon/misc.c
+daemon/server.c
+daemon/slave.c
+daemon/verify.c
+daemon/xdmcp.c
+gui/gdmchooser.c
+gui/gdmgreeter.c
+gui/gdmlogin.c
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 00000000..ce920fa4
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,865 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 1999-04-08 02:02+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: ENCODING\n"
+
+#: daemon/gdm.c:136
+#, c-format
+msgid "gdm_config_parse: No configuration file: %s. Aborting."
+msgstr "gdm_config_parse: Keine Konfigurationsdatei: %s. Breche ab."
+
+#: daemon/gdm.c:177
+msgid "gdm_config_parse: No greeter specified and default not found."
+msgstr ""
+"gdm_config_parse: Es wurde kein Greeter angegeben und Default nicht gefunden."
+
+#: daemon/gdm.c:189
+msgid "gdm_config_parse: No authdir specified and default not found."
+msgstr ""
+"gdm_config_parse: Es wurde kein authdir angegeben und Default nicht gefunden."
+
+#: daemon/gdm.c:207
+msgid ""
+"gdm_config_parse: No sessions directory specified and default not found."
+msgstr ""
+"gdm_config_parse: Es wurde kein Sitzungsverzeichnis angegeben und Default "
+"nicht gefunden."
+
+#: daemon/gdm.c:219
+#, fuzzy
+msgid "gdm_config_parse: Invalid server line in config file. Ignoring!"
+msgstr "gdm_config_parse: Keine Konfigurationsdatei: %s. Breche ab."
+
+#: daemon/gdm.c:225
+#, fuzzy
+msgid ""
+"gdm_config_parse: Xdmcp disabled and no local servers defined. Aborting!"
+msgstr "gdm_config_parse: Es wurden keine lokalen Server definiert."
+
+#: daemon/gdm.c:230
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm user (%s). Aborting!"
+msgstr "gdm_config_parse: Kann den gdm Benutzer (%s) nicht finden. Breche ab!"
+
+#: daemon/gdm.c:235
+#, fuzzy
+msgid "gdm_config_parse: The gdm user should not be root. Aborting!"
+msgstr "gdm_config_parse: Authdir %s existiert nicht. Breche ab."
+
+#: daemon/gdm.c:240
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm group (%s). Aborting!"
+msgstr "gdm_config_parse: Kann die gdm Gruppe (%s) nicht finden. Breche ab!"
+
+#: daemon/gdm.c:246
+#, fuzzy
+msgid "gdm_config_parse: The gdm group should not be root. Aborting!"
+msgstr "gdm_config_parse: Kann die gdm Gruppe (%s) nicht finden. Breche ab!"
+
+#: daemon/gdm.c:253
+#, c-format
+msgid "gdm_config_parse: Authdir %s does not exist. Aborting."
+msgstr "gdm_config_parse: Authdir %s existiert nicht. Breche ab."
+
+#: daemon/gdm.c:256
+#, c-format
+msgid "gdm_config_parse: Authdir %s is not a directory. Aborting."
+msgstr "gdm_config_parse: Authdir %s ist kein Verzeichnis. Breche ab."
+
+#: daemon/gdm.c:259
+#, c-format
+msgid ""
+"gdm_config_parse: Authdir %s is not owned by user %s, group %s. Aborting."
+msgstr ""
+"gdm_config_parse: Authdir %s gehört nicht Benutzer %s und Gruppe %s. Breche "
+"ab."
+
+#: daemon/gdm.c:262
+#, c-format
+msgid ""
+"gdm_config_parse: Authdir %s has wrong permissions. Should be 750. Aborting."
+msgstr ""
+"gdm_config_parse: Authdir %s hat falsche Zugriffsrechte. Sollte 750 sein. "
+"Breche ab."
+
+#: daemon/gdm.c:318
+#, c-format
+msgid "gdm_display_manage: Failed forking gdm slave process for %d"
+msgstr ""
+
+#: daemon/gdm.c:397
+#, c-format
+msgid "gdm_child_action: Aborting display %s"
+msgstr "gdm_child_action: Breche Display %s ab"
+
+#: daemon/gdm.c:402
+msgid "gdm_child_action: Master rebooting..."
+msgstr "gdm_child_action: Master rebooting..."
+
+#: daemon/gdm.c:408
+#, c-format
+msgid "gdm_child_action: Reboot failed: %s"
+msgstr "gdm_child_action: Neustart fehlgeschlagen: %s"
+
+#: daemon/gdm.c:412
+msgid "gdm_child_action: Master halting..."
+msgstr ""
+
+#: daemon/gdm.c:418
+#, c-format
+msgid "gdm_child_action: Halt failed: %s"
+msgstr "gdm_child_action: Anhalten fehlgeschlagen: %s"
+
+#: daemon/gdm.c:512
+msgid "gdm_daemonify: fork() failed!"
+msgstr "gdm_daemonify: fork() fehlgeschlagen!"
+
+#: daemon/gdm.c:515
+#, c-format
+msgid "gdm_daemonify: setsid() failed: %s!"
+msgstr "gdm_daemonify: setsid() fehlgeschlagen: %s!"
+
+#: daemon/gdm.c:540
+msgid "Only root wants to run gdm\n"
+msgstr "Nur root darf gdm starten\n"
+
+#: daemon/gdm.c:558
+msgid ""
+"gdm already running. Aborting!\n"
+"\n"
+msgstr ""
+"gdm läuft schon. Breche ab!\n"
+"\n"
+
+#: daemon/gdm.c:563
+#, c-format
+msgid ""
+"According to %s, gdm was already running (%d),\n"
+"but seems to have been murdered mysteriously.\n"
+msgstr ""
+
+#: daemon/gdm.c:584
+msgid "gdm_main: Error setting up TERM signal handler"
+msgstr ""
+
+#: daemon/gdm.c:587
+msgid "gdm_main: Error setting up INT signal handler"
+msgstr ""
+
+#: daemon/gdm.c:595
+msgid "gdm_main: Error setting up CHLD signal handler"
+msgstr ""
+
+#: daemon/auth.c:62
+#, c-format
+msgid "gdm_auth_secure_display: Could not unlink %s file: %s"
+msgstr ""
+
+#: daemon/auth.c:73
+#, c-format
+msgid ""
+"gdm_auth_secure_display: Error starting xauth process: %s. Running insecure!"
+msgstr ""
+
+#: daemon/auth.c:77
+msgid "gdm_auth_secure_display: Error forking xauth process. Running insecure!"
+msgstr ""
+
+#: daemon/auth.c:109
+#, c-format
+msgid "gdm_auth_user_add: Error starting xauth process: %s"
+msgstr ""
+
+#: daemon/auth.c:113
+msgid "gdm_auth_user_add: Error forking xauth process."
+msgstr ""
+
+#: daemon/auth.c:143
+#, c-format
+msgid "gdm_auth_user_remove: Error starting xauth process: %s"
+msgstr ""
+
+#: daemon/auth.c:147
+msgid "gdm_auth_user_remove: Error forking xauth process."
+msgstr ""
+
+#: daemon/filecheck.c:50 daemon/filecheck.c:83
+#, c-format
+msgid "%s: %s is not owned by uid %d. Skipping."
+msgstr "%s: %s is not owned by uid %d. Skipping."
+
+#: daemon/filecheck.c:57
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 755. Skipping."
+msgstr ""
+"%s: %s ist beschreibbar durch Gruppe/Andere. Sollte 755 sein. Überspringe."
+
+#: daemon/filecheck.c:76
+#, c-format
+msgid "%s: %s is not a regular file. Skipping."
+msgstr "%s: %s ist keine reguläre Datei. Überspringe."
+
+#: daemon/filecheck.c:90
+#, fuzzy, c-format
+msgid "%s: %s is writable by group. Should be 644. Skipping."
+msgstr ""
+"%s: %s ist schreibbar durch Gruppe/Andere. Sollte 644 sein. Überspringe."
+
+#: daemon/filecheck.c:97
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 644. Skipping."
+msgstr ""
+"%s: %s ist schreibbar durch Gruppe/Andere. Sollte 644 sein. Überspringe."
+
+#: daemon/filecheck.c:104
+#, c-format
+msgid "%s: %s is bigger than sysadmin specified maximum file size. Skipping."
+msgstr ""
+"%s: %s ist größer als die durch den Systemadministrator spezifizierte "
+"maximale Dateigröße. Überspringe."
+
+#: daemon/misc.c:121
+#, c-format
+msgid "gdm_exec_script: Failed starting: %s"
+msgstr ""
+
+#: daemon/misc.c:125
+msgid "gdm_exec_script: Can't fork script process!"
+msgstr ""
+
+#: daemon/misc.c:153
+#, c-format
+msgid "gdm_exec_command: Failed starting: %s"
+msgstr ""
+
+#: daemon/misc.c:157
+msgid "gdm_exec_command: Can't fork process!"
+msgstr ""
+
+#: daemon/server.c:82 daemon/server.c:213
+#, fuzzy
+msgid "gdm_server_start: Error setting up USR1 signal handler"
+msgstr "gdm_slave_xsync_ping: Fehler beim Einrichten des ALARM signal handlers"
+
+#: daemon/server.c:99
+#, fuzzy, c-format
+msgid "gdm_server_start: Could not open logfile for display %s!"
+msgstr "gdm_xdmcp_handle_manage: Konnte Logdatei für Display %s nicht öffnen!"
+
+#: daemon/server.c:129
+msgid "gdm_server_start: Error setting USR1 to SIG_IGN"
+msgstr ""
+
+#: daemon/server.c:146
+#, fuzzy, c-format
+msgid "gdm_server_start: Xserver not found: %s"
+msgstr "gdm_local_servers_start: Starte %s"
+
+#: daemon/server.c:152
+msgid "gdm_server_start: Can't fork Xserver process!"
+msgstr ""
+
+#: daemon/server.c:178
+#, c-format
+msgid "gdm_server_stop: Could not unlink auth file: %s!"
+msgstr ""
+
+#: daemon/server.c:237
+#, fuzzy
+msgid "gdm_server_restart: Error setting up ALARM signal handler"
+msgstr "gdm_slave_xsync_ping: Fehler beim Einrichten des ALARM signal handlers"
+
+#: daemon/slave.c:112
+msgid "gdm_slave_init: Error setting up TERM/INT signal handler"
+msgstr ""
+
+#: daemon/slave.c:120
+msgid "gdm_slave_init: Error setting up CHLD signal handler"
+msgstr ""
+
+#: daemon/slave.c:171
+msgid "gdm_slave_greeter: Can't init pipe to gdmgreeter"
+msgstr ""
+
+#: daemon/slave.c:196
+#, c-format
+msgid "gdm_slave_greeter: Couldn't set groupid to %d"
+msgstr ""
+
+#: daemon/slave.c:199
+#, c-format
+msgid "gdm_slave_greeter: Couldn't set userid to %d"
+msgstr ""
+
+#: daemon/slave.c:209
+#, c-format
+msgid "gdm_slave_greeter: Error starting greeter on display %s"
+msgstr ""
+
+#: daemon/slave.c:212
+msgid "gdm_slave_greeter: Can't fork gdmgreeter process"
+msgstr ""
+
+#: daemon/slave.c:280
+#, c-format
+msgid "gdm_slave_session_init: User '%s' not found. Aborting."
+msgstr ""
+
+#: daemon/slave.c:299
+msgid ""
+"gdm_slave_session_init: Execution of PreSession script returned > 0. "
+"Aborting."
+msgstr ""
+
+#: daemon/slave.c:304
+msgid "gdm_slave_session_init: Error forking user session"
+msgstr ""
+
+#: daemon/slave.c:312
+#, c-format
+msgid "gdm_slave_session_init: Could not setgid %d. Aborting."
+msgstr ""
+
+#: daemon/slave.c:315
+#, c-format
+msgid "gdm_slave_session_init: initgroups() failed for %s. Aborting."
+msgstr ""
+
+#: daemon/slave.c:318
+#, c-format
+msgid "gdm_slave_session_init: Could not become %s. Aborting."
+msgstr ""
+
+#: daemon/slave.c:373
+#, c-format
+msgid "gdm_slave_session_init: Could not start session `%s'"
+msgstr ""
+
+#: daemon/slave.c:547
+#, c-format
+msgid "gdm_slave_windows_kill_ioerror_handler: Fatal X error - Restarting %s"
+msgstr ""
+"gdm_slave_windows_kill_ioerror_handler: Fataler X Fehler - Starte %s erneut"
+
+#: daemon/slave.c:579
+msgid "gdm_slave_xsync_ping: Error setting up ALARM signal handler"
+msgstr "gdm_slave_xsync_ping: Fehler beim Einrichten des ALARM signal handlers"
+
+#: daemon/verify.c:122 daemon/verify.c:185 gui/gdmgreeter.c:1363
+msgid "Login:"
+msgstr ""
+
+#: daemon/verify.c:128
+msgid "Can't find /etc/pam.d/gdm!"
+msgstr "Kann /etc/pam.d/gdm nicht finden!"
+
+#: daemon/verify.c:132
+#, c-format
+msgid "Can't set PAM_TTY=%s"
+msgstr "Kann PAM_TTY=%s nicht setzen"
+
+#: daemon/verify.c:137 daemon/verify.c:189
+#, c-format
+msgid "Couldn't authenticate %s"
+msgstr "Konnte %s nicht beglaubigen"
+
+#: daemon/verify.c:142
+#, c-format
+msgid "Couldn't set acct. mgmt for %s"
+msgstr "Konnte acct. mgmt für %s nicht setzen"
+
+#: daemon/verify.c:147
+#, c-format
+msgid "Couldn't set credentials for %s"
+msgstr "Konnte Berechtigungsnachweise für %s nicht setzen"
+
+#: daemon/verify.c:152
+#, c-format
+msgid "Couldn't open session for %s"
+msgstr "Konnte Session für %s nicht öffnen"
+
+#: daemon/verify.c:192
+msgid "User unknown"
+msgstr ""
+
+#: daemon/verify.c:208 gui/gdmgreeter.c:1369
+msgid "Password:"
+msgstr "Passwort:"
+
+#: daemon/verify.c:213
+msgid "Incorrect password"
+msgstr ""
+
+#: daemon/xdmcp.c:172
+#, c-format
+msgid "gdm_xdmcp_init: Could not get server hostname: %s!"
+msgstr "gdm_xdmcp_init: Konnte Server Hostname nicht bekommen: %s!"
+
+#: daemon/xdmcp.c:183
+msgid "gdm_xdmcp_init: Could not create socket!"
+msgstr "gdm_xdmcp_init: Konnte Socket nicht erzeugen!"
+
+#: daemon/xdmcp.c:190
+msgid "gdm_xdmcp_init: Could not bind to XDMCP socket!"
+msgstr "gdm_xdmcp_init: Konnte nicht an XDMCP Socket binden!"
+
+#: daemon/xdmcp.c:225
+msgid "gdm_xdmcp_decode: Could not create XDMCP buffer!"
+msgstr "gdm_xdmcp_decode: Konnte XDMCP Buffer nicht erzeugen!"
+
+#: daemon/xdmcp.c:230
+msgid "gdm_xdmcp_decode: Could not read XDMCP header!"
+msgstr "gdm_xdmcp_decode: Konnte XDMCP Header nicht lesen!"
+
+#: daemon/xdmcp.c:235
+msgid "gdm_xdmcp_decode: Incorrect XDMCP version!"
+msgstr "gdm_xdmcp_decode: Falsche XDMCP Version!"
+
+#: daemon/xdmcp.c:271
+#, c-format
+msgid "gdm_xdmcp_decode_packet: Unknown opcode from host %s"
+msgstr "gdm_xdmcp_decode_packet: Unbekannter Opcode von Host %s"
+
+#: daemon/xdmcp.c:289
+msgid "gdm_xdmcp_query: Could not extract authlist from packet"
+msgstr "gdm_xdmcp_query: Konnte authlist vom Paket nicht extrahieren"
+
+#: daemon/xdmcp.c:300
+msgid "gdm_xdmcp_query: Error in checksum"
+msgstr "gdm_xdmcp_query: Fehler in Prüfsumme"
+
+#: daemon/xdmcp.c:323
+msgid "GNOME"
+msgstr ""
+
+#: daemon/xdmcp.c:347
+#, c-format
+msgid "Denied XDMCP query from host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:349
+msgid "Display not authorized to connect"
+msgstr "Display ist nicht autorisiert zu verbinden"
+
+#: daemon/xdmcp.c:382
+#, c-format
+msgid "gdm_xdmcp_handle_request: Got REQUEST from banned host %s"
+msgstr "gdm_xdmcp_handle_request: REQUEST von gesperrtem Host %s bekommen"
+
+#: daemon/xdmcp.c:389
+msgid "gdm_xdmcp_handle_request: Could not read Display Number"
+msgstr "gdm_xdmcp_handle_request: Konnte Display Nummer nicht lesen"
+
+#: daemon/xdmcp.c:395
+msgid "gdm_xdmcp_handle_request: Could not read Connection Type"
+msgstr "gdm_xdmcp_handle_request: Konnte Verbindungstyp nicht lesen"
+
+#: daemon/xdmcp.c:401
+msgid "gdm_xdmcp_handle_request: Could not read Client Address"
+msgstr "gdm_xdmcp_handle_request: Konnte Client Adresse nicht lesen"
+
+#: daemon/xdmcp.c:407
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Names"
+msgstr "gdm_xdmcp_handle_request: Konnte Authentication Namen nicht lesen"
+
+#: daemon/xdmcp.c:413
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Data"
+msgstr "gdm_xdmcp_handle_request: Konnte Authentication Data nicht lesen"
+
+#: daemon/xdmcp.c:419
+msgid "gdm_xdmcp_handle_request: Could not read Authorization List"
+msgstr "gdm_xdmcp_handle_request: Konnte Authorization List nicht lesen"
+
+#: daemon/xdmcp.c:430
+msgid "gdm_xdmcp_handle_request: Could not read Manufacturer ID"
+msgstr "gdm_xdmcp_handle_request: Konnte Manufacturer ID nicht lesen"
+
+#: daemon/xdmcp.c:448
+#, c-format
+msgid "gdm_xdmcp_handle_request: Failed checksum from %s"
+msgstr "gdm_xdmcp_handle_request: Fehlgeschlagene Prüfsumme von %s"
+
+#: daemon/xdmcp.c:566
+#, c-format
+msgid "gdm_xdmcp_handle_manage: Got Manage from banned host %s"
+msgstr "gdm_xdmcp_handle_manage: Manage von gesperrtem Host %s bekommen"
+
+#: daemon/xdmcp.c:573
+msgid "gdm_xdmcp_handle_manage: Could not read Session ID"
+msgstr "gdm_xdmcp_handle_manage: Konnte Session ID nicht lese"
+
+#: daemon/xdmcp.c:579
+msgid "gdm_xdmcp_handle_manage: Could not read Display Number"
+msgstr "gdm_xdmcp_handle_manage: Konnte Display Nummer nicht lesen"
+
+#: daemon/xdmcp.c:588
+msgid "gdm_xdmcp_manage: Could not read Display Class"
+msgstr "gdm_xdmcp_manage: Konnte Display Class nicht lesen"
+
+#: daemon/xdmcp.c:607
+#, c-format
+msgid "gdm_xdmcp_handle_manage: Could not open logfile for display %s!"
+msgstr "gdm_xdmcp_handle_manage: Konnte Logdatei für Display %s nicht öffnen!"
+
+#: daemon/xdmcp.c:679
+#, c-format
+msgid "gdm_xdmcp_handle_keepalive: Got KEEPALIVE from banned host %s"
+msgstr "gdm_xdmcp_handle_keepalive: KEEPALIVE von gesperrtem Host %s bekommen"
+
+#: daemon/xdmcp.c:686
+msgid "gdm_xdmcp_handle_keepalive: Could not read Display Number"
+msgstr "gdm_xdmcp_handle_keepalive: Konnte Display Nummer nicht lesen"
+
+#: daemon/xdmcp.c:692
+msgid "gdm_xdmcp_handle_keepalive: Could not read Session ID"
+msgstr "gdm_xdmcp_handle_keepalive: Konnte Session ID nicht lesen"
+
+#: gui/gdmchooser.c:336
+#, fuzzy, c-format
+msgid "gdm_chooser_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_greeter_parse_config: Keine Konfigurationsdatei: %s. Breche ab."
+
+#: gui/gdmchooser.c:447
+#, fuzzy, c-format
+msgid "Can't open default host icon: %s"
+msgstr "Konnte Session für %s nicht öffnen"
+
+#. Buttons
+#: gui/gdmchooser.c:512
+msgid "Connect"
+msgstr ""
+
+#: gui/gdmchooser.c:519
+msgid "Rescan"
+msgstr ""
+
+#: gui/gdmchooser.c:525
+msgid "Cancel"
+msgstr ""
+
+#: gui/gdmchooser.c:576 gui/gdmgreeter.c:1672 gui/gdmlogin.c:1102
+msgid "main: Error setting up HUP signal handler"
+msgstr ""
+
+#: gui/gdmchooser.c:579 gui/gdmgreeter.c:1675 gui/gdmlogin.c:1105
+msgid "main: Error setting up INT signal handler"
+msgstr ""
+
+#: gui/gdmchooser.c:582 gui/gdmgreeter.c:1678 gui/gdmlogin.c:1108
+msgid "main: Error setting up TERM signal handler"
+msgstr ""
+
+#: gui/gdmgreeter.c:155
+msgid "Gnome Display Manager"
+msgstr ""
+
+#: gui/gdmgreeter.c:157
+msgid "Copyright Martin K. Petersen (C) 1998, 1999"
+msgstr ""
+
+#: gui/gdmgreeter.c:159 gui/gdmlogin.c:328
+msgid ""
+"gdm manages local and remote displays and provides the user with a login "
+"window."
+msgstr ""
+"gdm verwaltet lokale und entfernte Displays und stellt dem Benutzer ein "
+"Login-Fenster bereit."
+
+#: gui/gdmgreeter.c:194 gui/gdmlogin.c:271
+msgid "gdm_parse_enriched_string: String too long!"
+msgstr "gdm_parse_enriched_string: String ist zu lang!"
+
+#: gui/gdmgreeter.c:195 gui/gdmlogin.c:272
+msgid "Welcome to "
+msgstr "Willkommen bei "
+
+#: gui/gdmgreeter.c:199 gui/gdmlogin.c:276
+msgid "gdm_parse_enriched_string: Could not malloc temporary buffer!"
+msgstr "gdm_parse_enriched_string: Konnte temporären Buffer nicht allokieren!"
+
+#: gui/gdmgreeter.c:273
+msgid "Logo not found. No image will be displayed!"
+msgstr "Logo wurde nicht gefunden. Es wird kein Bild angezeigt!"
+
+#: gui/gdmgreeter.c:299
+#, c-format
+msgid "gdm_greeter_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_greeter_parse_config: Keine Konfigurationsdatei: %s. Breche ab."
+
+#: gui/gdmgreeter.c:323 gui/gdmlogin.c:403
+#, c-format
+msgid "messages/welcome=Welcome to %h"
+msgstr ""
+
+#: gui/gdmgreeter.c:424 gui/gdmlogin.c:527 gui/gdmlogin.c:557
+#, c-format
+msgid ""
+"You have chosen %s for this session, but your default setting is %s.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Sie haben %s für diese Sitzung ausgewählt. Ihr Default-Einstellung ist aber "
+"%s.\n"
+"Möchten Sie %s zu Ihrer Default-Einstellung für zukünftige Sitzungen machen?"
+
+#: gui/gdmgreeter.c:432
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Ihr vorheriger Sitzungstyp %s ist auf diesem Rechner nicht installiert.\n"
+"Möchten Sie %s zu Ihrer Default-Einstellung für zukünftige Sitzungen machen?"
+
+#: gui/gdmgreeter.c:440
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"You will be logged in using the %s environment."
+msgstr ""
+"Ihr vorheriger Sitzungstyp %s ist auf diesem Rechner nicht installiert.\n"
+"Sie werden mit der %s Umgebung eingeloggt werden."
+
+#: gui/gdmgreeter.c:453
+#, c-format
+msgid ""
+"You have chosen the language %s for this session, but your default setting "
+"is %s.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+"Sie haben die Sprache %s für diese Sitzung ausgewählt. Ihre "
+"Default-Einstellung ist %s.\n"
+"Möchten Sie %s zu Ihrer Default-Sprache für zukünftige Sitzungen machen?"
+
+#: gui/gdmgreeter.c:461
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+"Ihre vorherige Sprache %s ist auf diesem Rechner nicht installiert.\n"
+"Möchten Sie %s zu Ihrer Default-Sprache für zukünftige Sitzungen machen?"
+
+#: gui/gdmgreeter.c:469
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Your environment will be %s."
+msgstr ""
+"Ihre vorherige Sprache %s ist auf diesem Rechner nicht installiert.\n"
+"Ihre Umgebung wird %s sein."
+
+#: gui/gdmgreeter.c:500
+msgid "Invalid username or password!"
+msgstr "Ungültiger Benutzername oder Passwort!"
+
+#: gui/gdmgreeter.c:526 gui/gdmlogin.c:354
+msgid "Are you sure you want to reboot the machine?"
+msgstr "Sind Sie sicher, daß sie den Rechner neu starten möchten?"
+
+#: gui/gdmgreeter.c:555 gui/gdmlogin.c:366
+msgid "Are you sure you want to halt the machine?"
+msgstr "Sind Sie sicher, daß sie den Rechner anhalten möchten?"
+
+#: gui/gdmgreeter.c:812
+msgid "gdm_greeter_session_init: Session script directory not found!"
+msgstr "gdm_greeter_session_init: Sitzungs-Skript Verzeichnis nicht gefunden!"
+
+#: gui/gdmgreeter.c:865 gui/gdmlogin.c:694
+msgid "No session scripts found. Aborting!"
+msgstr "Keine Sitzungs-Skripte gefunden. Breche ab!"
+
+#: gui/gdmgreeter.c:869 gui/gdmlogin.c:698
+#, c-format
+msgid "No default session link found. Using %s.\n"
+msgstr "Keinen Default Sitzungs-Link gefunden. Benutze %s.\n"
+
+#. Login button
+#: gui/gdmgreeter.c:1029
+msgid "Login"
+msgstr ""
+
+#. Init sessions menu
+#: gui/gdmgreeter.c:1041
+msgid "Sessions"
+msgstr "Sitzungen"
+
+#. Language selection support
+#: gui/gdmgreeter.c:1048
+msgid "Languages"
+msgstr "Sprachen"
+
+#: gui/gdmgreeter.c:1058 gui/gdmlogin.c:960
+msgid "Reboot..."
+msgstr "Neustart..."
+
+#: gui/gdmgreeter.c:1064 gui/gdmlogin.c:966
+msgid "Halt..."
+msgstr "Anhalten (Halt)"
+
+#: gui/gdmgreeter.c:1071
+msgid "Suspend"
+msgstr "Suspendieren"
+
+#: gui/gdmgreeter.c:1078 gui/gdmlogin.c:972
+msgid "System"
+msgstr ""
+
+#: gui/gdmgreeter.c:1086 gui/gdmlogin.c:986
+#, c-format
+msgid "Can't open icon file: %s. Suspending iconify feature!"
+msgstr ""
+
+#: gui/gdmgreeter.c:1090 gui/gdmlogin.c:990
+msgid "Iconify"
+msgstr "Ikonifizieren"
+
+#. Option button
+#: gui/gdmgreeter.c:1099
+msgid "Options..."
+msgstr "Optionen..."
+
+#: gui/gdmgreeter.c:1531
+#, c-format
+msgid "Can't open NofaceImageFile: %s. Suspending face browser!"
+msgstr ""
+
+#: gui/gdmgreeter.c:1686
+msgid "main: Error setting up USR1 signal handler"
+msgstr ""
+
+#: gui/gdmgreeter.c:1694
+msgid "main: Error setting up USR2 signal handler"
+msgstr ""
+
+#: gui/gdmlogin.c:382
+#, fuzzy, c-format
+msgid "gdm_login_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_greeter_parse_config: Keine Konfigurationsdatei: %s. Breche ab."
+
+#: gui/gdmlogin.c:508
+#, fuzzy, c-format
+msgid ""
+"Your preferred session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Ihr vorheriger Sitzungstyp %s ist auf diesem Rechner nicht installiert.\n"
+"Möchten Sie %s zu Ihrer Default-Einstellung für zukünftige Sitzungen machen?"
+
+#: gui/gdmlogin.c:616
+#, c-format
+msgid "%s session selected"
+msgstr ""
+
+#: gui/gdmlogin.c:632 gui/gdmlogin.c:723
+msgid "Last"
+msgstr ""
+
+#: gui/gdmlogin.c:647
+#, fuzzy
+msgid "gdm_login_session_init: Session script directory not found!"
+msgstr "gdm_greeter_session_init: Sitzungs-Skript Verzeichnis nicht gefunden!"
+
+#: gui/gdmlogin.c:709
+#, c-format
+msgid "%s language selected"
+msgstr ""
+
+#: gui/gdmlogin.c:736
+msgid "A-M"
+msgstr ""
+
+#: gui/gdmlogin.c:742
+msgid "N-Z"
+msgstr ""
+
+#: gui/gdmlogin.c:748
+msgid "Other"
+msgstr ""
+
+#: gui/gdmlogin.c:946
+#, fuzzy
+msgid "Session"
+msgstr "Sitzungen"
+
+#: gui/gdmlogin.c:953
+#, fuzzy
+msgid "Language"
+msgstr "Sprachen"
+
+#: gui/gdmlogin.c:979
+msgid "Host chooser"
+msgstr ""
+
+#, fuzzy
+#~ msgid "gdm_server_usr1_handler: Could not open display %s"
+#~ msgstr "gdm_slave_windows_kill: Konnte Display %s nicht öffnen"
+
+#, fuzzy
+#~ msgid "gdm_display_dispose: Closing display %s"
+#~ msgstr "gdm_child_action: Breche Display %s ab"
+
+#~ msgid "gdm_display_manage: Managing %s"
+#~ msgstr "gdm_display_manage: Verwalte %s"
+
+#~ msgid "gdm_child_action: Server process returned unknown status %d"
+#~ msgstr ""
+#~ "gdm_child_action: Der Server Prozeß hat einen unbekannten Status %d "
+#~ "zurückgegeben"
+
+#, fuzzy
+#~ msgid "gdm_child_action: Slave process returned unknown status %d"
+#~ msgstr ""
+#~ "gdm_child_action: Slave Proceß hat unbekannten Status zurückgegeben!"
+
+#~ msgid "gdm_child_handler: child %d returned %d"
+#~ msgstr "gdm_child_handler: Kind %d gab %d zurück"
+
+#~ msgid "gdm_display_unmanage: Stopping %s"
+#~ msgstr "gdm_display_unmanage: Stoppe %s"
+
+#~ msgid "gdm_term_handler: Got TERM/INT. Going down!"
+#~ msgstr "gdm_term_handler: TERM/INT empfangen. Fahre runter!"
+
+#~ msgid "gdm_slave_xioerror_handler: I/O error for display %s"
+#~ msgstr "gdm_slave_xioerror_handler: I/O Fehler für Display %s"
+
+#~ msgid "gdm_slave_xsync_handler: Xping failed for display %s"
+#~ msgstr "gdm_slave_xsync_handler: Xping für Display %s fehlgeschlagen"
+
+#~ msgid "gdm_slave_xsync_ping: Pinging %s returned %d"
+#~ msgstr "gdm_slave_xsync_ping: Ping an %s ergab %d"
+
+#~ msgid "gdm_xdmcp_send_willing: Sending WILLING to %s"
+#~ msgstr "gdm_xdmcp_send_willing: Sende WILLING an %s"
+
+#~ msgid "gdm_xdmcp_send_unwilling: Sending UNWILLING to %s"
+#~ msgstr "gdm_xdmcp_send_unwilling: Sende UNWILLING an %s"
+
+#~ msgid "gdm_xdmcp_handle_request: Got REQUEST from %s"
+#~ msgstr "gdm_xdmcp_handle_request: REQUEST von %s bekommen"
+
+#~ msgid "gdm_xdmcp_send_accept: Sending ACCEPT to %s with SessionID=%d"
+#~ msgstr "gdm_xdmcp_send_accept: Sende ACCEPT an %s mit SessionID=%d"
+
+#~ msgid "gdm_xdmcp_send_decline: Sending DECLINE to %s"
+#~ msgstr "gdm_xdmcp_send_decline: Sende DECLINE an %s"
+
+#~ msgid "gdm_xdmcp_manage: Got MANAGE from %s"
+#~ msgstr "gdm_xdmcp_manage: MANAGE von %s bekommen"
+
+#~ msgid "gdm_xdmcp_manage: Got Display=%d, SessionID=%d from %s"
+#~ msgstr "gdm_xdmcp_manage: Display=%d, SessionID=%d von %s bekommen"
+
+#~ msgid "gdm_xdmcp_handle_keepalive: Got KEEPALIVE from %s"
+#~ msgstr "gdm_xdmcp_handle_keepalive: KEEPALIVE von %s bekommen"
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 00000000..869d2405
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,954 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gdm 0.7.9\n"
+"POT-Creation-Date: 1999-04-08 02:02+0200\n"
+"PO-Revision-Date: 1998-11-21 01:59:37+0100\n"
+"Last-Translator: Pablo Saratxaga <srtxg@chanae.alphanet.ch>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Date: 1998-11-21 01:59:37+0100\n"
+"From: Pablo Saratxaga <srtxg@chanae.alphanet.ch>\n"
+"Xgettext-Options: --default-domain=gdm --directory=.. --add-comments "
+"--keyword=_ --keyword=N_ --files-from=./POTFILES.in\n"
+"Files: src/gdm.c src/gdmauth.c src/gdmgreeter.c src/gdmslave.c "
+"src/gdmverify.c\n"
+
+#: daemon/gdm.c:136
+#, c-format
+msgid "gdm_config_parse: No configuration file: %s. Aborting."
+msgstr "gdm_config_parse: Ningún archivo de configuración: %s. Abortando."
+
+#: daemon/gdm.c:177
+msgid "gdm_config_parse: No greeter specified and default not found."
+msgstr ""
+"gdm_config_parse: no se especificó un programa de bienvenida y no se "
+"encontró a gdmgreeter"
+
+#: daemon/gdm.c:189
+msgid "gdm_config_parse: No authdir specified and default not found."
+msgstr ""
+"gdm_config_parse: no se especificó el directorio authdir y no se encontró el "
+"normal"
+
+#: daemon/gdm.c:207
+msgid ""
+"gdm_config_parse: No sessions directory specified and default not found."
+msgstr ""
+"gdm_config_parse: No se especificó el directorio de sesiones y no encontré "
+"el mio"
+
+#: daemon/gdm.c:219
+#, fuzzy
+msgid "gdm_config_parse: Invalid server line in config file. Ignoring!"
+msgstr "gdm_config_parse: Ningún archivo de configuración: %s. Abortando."
+
+#: daemon/gdm.c:225
+#, fuzzy
+msgid ""
+"gdm_config_parse: Xdmcp disabled and no local servers defined. Aborting!"
+msgstr "gdm_config_parse: No hay servidores locales definidos."
+
+#: daemon/gdm.c:230
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm user (%s). Aborting!"
+msgstr "gdm_config_parse: No se encuentra el usuario de gdm (%s). Abortando."
+
+#: daemon/gdm.c:235
+#, fuzzy
+msgid "gdm_config_parse: The gdm user should not be root. Aborting!"
+msgstr ""
+"gdm_config_parse: El directorio de autorizaciones %s no existe. Abortando."
+
+#: daemon/gdm.c:240
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm group (%s). Aborting!"
+msgstr "gdm_config_parse: No se encuentra el grupo de gdm (%s). Abortando."
+
+#: daemon/gdm.c:246
+#, fuzzy
+msgid "gdm_config_parse: The gdm group should not be root. Aborting!"
+msgstr "gdm_config_parse: No se encuentra el grupo de gdm (%s). Abortando."
+
+#: daemon/gdm.c:253
+#, c-format
+msgid "gdm_config_parse: Authdir %s does not exist. Aborting."
+msgstr ""
+"gdm_config_parse: El directorio de autorizaciones %s no existe. Abortando."
+
+#: daemon/gdm.c:256
+#, c-format
+msgid "gdm_config_parse: Authdir %s is not a directory. Aborting."
+msgstr "gdm_config_parse: %s no es un directorio. Abortando."
+
+#: daemon/gdm.c:259
+#, c-format
+msgid ""
+"gdm_config_parse: Authdir %s is not owned by user %s, group %s. Aborting."
+msgstr ""
+"gdm_config_parse: El directorio de autorizaciones %s no pertenece al usuario "
+"%s, grupo %s. Abortando."
+
+#: daemon/gdm.c:262
+#, c-format
+msgid ""
+"gdm_config_parse: Authdir %s has wrong permissions. Should be 750. Aborting."
+msgstr ""
+"gdm_config_parse: El directorio de autorizaciones %s tiene permisos "
+"incorrectos. Debe de ser 750. Abortando."
+
+#: daemon/gdm.c:318
+#, c-format
+msgid "gdm_display_manage: Failed forking gdm slave process for %d"
+msgstr "gdm_display_manager: falla al crear el proceso esclavo para %d"
+
+#: daemon/gdm.c:397
+#, c-format
+msgid "gdm_child_action: Aborting display %s"
+msgstr "gdm_child_action: Abortando el despliegue %s"
+
+#: daemon/gdm.c:402
+msgid "gdm_child_action: Master rebooting..."
+msgstr "gdm_child_action: Reiniciando el maestro"
+
+#: daemon/gdm.c:408
+#, c-format
+msgid "gdm_child_action: Reboot failed: %s"
+msgstr "gdm_child_action: Falla al reiniciar: %s"
+
+#: daemon/gdm.c:412
+msgid "gdm_child_action: Master halting..."
+msgstr "gdm_child_action: Deteniendo al maestro"
+
+#: daemon/gdm.c:418
+#, c-format
+msgid "gdm_child_action: Halt failed: %s"
+msgstr "gdm_child_action: Falla al detener: %s"
+
+#: daemon/gdm.c:512
+msgid "gdm_daemonify: fork() failed!"
+msgstr "gdm_daemonify: falla en fork()"
+
+#: daemon/gdm.c:515
+#, c-format
+msgid "gdm_daemonify: setsid() failed: %s!"
+msgstr "gdm_daemonify: setsid () falló: %s"
+
+#: daemon/gdm.c:540
+msgid "Only root wants to run gdm\n"
+msgstr "Solamente root puede ejecutar gdm\n"
+
+#: daemon/gdm.c:558
+msgid ""
+"gdm already running. Aborting!\n"
+"\n"
+msgstr ""
+"gdm ya se encuentra ejecutándose. Abortando!\n"
+"\n"
+
+#: daemon/gdm.c:563
+#, fuzzy, c-format
+msgid ""
+"According to %s, gdm was already running (%d),\n"
+"but seems to have been murdered mysteriously.\n"
+msgstr ""
+"gdm ya se encontraba corriendo (%d) pero parece que fue matado "
+"misteriosamente\n"
+
+#: daemon/gdm.c:584
+msgid "gdm_main: Error setting up TERM signal handler"
+msgstr "gdm_main: Error al configurar el controlador de la señal TERM"
+
+#: daemon/gdm.c:587
+msgid "gdm_main: Error setting up INT signal handler"
+msgstr "gdm_main: Error al configurar el controlador de la señal INT"
+
+#: daemon/gdm.c:595
+msgid "gdm_main: Error setting up CHLD signal handler"
+msgstr "gdm_main: Error al configurar el controlador de la señal CHLD"
+
+#: daemon/auth.c:62
+#, c-format
+msgid "gdm_auth_secure_display: Could not unlink %s file: %s"
+msgstr "gdm_auth_secure_display: No se pudo hacer un unlink del archivo %s: %s"
+
+#: daemon/auth.c:73
+#, c-format
+msgid ""
+"gdm_auth_secure_display: Error starting xauth process: %s. Running insecure!"
+msgstr ""
+"gdm_auth_secure_display: Error al lanzar el proceso xauth: %s. ¡Corriendo de "
+"manera no segura!"
+
+#: daemon/auth.c:77
+msgid "gdm_auth_secure_display: Error forking xauth process. Running insecure!"
+msgstr ""
+"gdm_auth_secure_display: Error al hacer un fork del proceso xauth. "
+"¡Corriendo de manera no segura!"
+
+#: daemon/auth.c:109
+#, c-format
+msgid "gdm_auth_user_add: Error starting xauth process: %s"
+msgstr "gdm_auth_user_add: Error al lanzar el proceso xauth: %s"
+
+#: daemon/auth.c:113
+msgid "gdm_auth_user_add: Error forking xauth process."
+msgstr "gdm_auth_user_add: Error al hacer un fork del proceso xauth."
+
+#: daemon/auth.c:143
+#, c-format
+msgid "gdm_auth_user_remove: Error starting xauth process: %s"
+msgstr "gdm_auth_user_remove: Error al lanzar el proceso xauth: %s"
+
+#: daemon/auth.c:147
+msgid "gdm_auth_user_remove: Error forking xauth process."
+msgstr "gdm_auth_user_remove: Error al hacer un fork del proceso xauth."
+
+#: daemon/filecheck.c:50 daemon/filecheck.c:83
+#, c-format
+msgid "%s: %s is not owned by uid %d. Skipping."
+msgstr "%s: %s no tiene como dueño el uid %d. Ignorando."
+
+#: daemon/filecheck.c:57
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 755. Skipping."
+msgstr ""
+"%s: %s puede ser escrito por el grupo y otros. Debería de tener permisos "
+"0755. Ignorando"
+
+#: daemon/filecheck.c:76
+#, c-format
+msgid "%s: %s is not a regular file. Skipping."
+msgstr "%s: %s no es un archivo regular. Ignorando"
+
+#: daemon/filecheck.c:90
+#, fuzzy, c-format
+msgid "%s: %s is writable by group. Should be 644. Skipping."
+msgstr ""
+"%s: %s puede ser escrito por el grupo y otros. Debería de ser 644. "
+"Ignorando."
+
+#: daemon/filecheck.c:97
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 644. Skipping."
+msgstr ""
+"%s: %s puede ser escrito por el grupo y otros. Debería de ser 644. "
+"Ignorando."
+
+#: daemon/filecheck.c:104
+#, c-format
+msgid "%s: %s is bigger than sysadmin specified maximum file size. Skipping."
+msgstr ""
+"%s: %s es mayor que el tamaño máximo de archivos especificado por el "
+"administrador. Salteandolo."
+
+#: daemon/misc.c:121
+#, c-format
+msgid "gdm_exec_script: Failed starting: %s"
+msgstr "gdm_exec_script: Falló el lanzamiento: %s"
+
+#: daemon/misc.c:125
+msgid "gdm_exec_script: Can't fork script process!"
+msgstr "gdm_exec_script: ¡Imposible de hacer un fork para el proceso script!"
+
+#: daemon/misc.c:153
+#, c-format
+msgid "gdm_exec_command: Failed starting: %s"
+msgstr "gdm_exec_command: Falló el lanzamiento: %s"
+
+#: daemon/misc.c:157
+msgid "gdm_exec_command: Can't fork process!"
+msgstr "gdm_exec_command: ¡Imposible de hacer un fork para el proceso!"
+
+#: daemon/server.c:82 daemon/server.c:213
+#, fuzzy
+msgid "gdm_server_start: Error setting up USR1 signal handler"
+msgstr "main: Error al configurar el controlador de la señal USR1"
+
+#: daemon/server.c:99
+#, fuzzy, c-format
+msgid "gdm_server_start: Could not open logfile for display %s!"
+msgstr "gdm_slave_windows_kill: No pude abrir el display %s"
+
+#: daemon/server.c:129
+msgid "gdm_server_start: Error setting USR1 to SIG_IGN"
+msgstr ""
+
+#: daemon/server.c:146
+#, fuzzy, c-format
+msgid "gdm_server_start: Xserver not found: %s"
+msgstr "gdm_local_servers_start: Lanzando %s"
+
+#: daemon/server.c:152
+#, fuzzy
+msgid "gdm_server_start: Can't fork Xserver process!"
+msgstr "gdm_exec_script: ¡Imposible de hacer un fork para el proceso script!"
+
+#: daemon/server.c:178
+#, fuzzy, c-format
+msgid "gdm_server_stop: Could not unlink auth file: %s!"
+msgstr "gdm_auth_secure_display: No se pudo hacer un unlink del archivo %s: %s"
+
+#: daemon/server.c:237
+#, fuzzy
+msgid "gdm_server_restart: Error setting up ALARM signal handler"
+msgstr "main: Error al configurar el controlador de la señal USR1"
+
+#: daemon/slave.c:112
+msgid "gdm_slave_init: Error setting up TERM/INT signal handler"
+msgstr ""
+"gdm_slave_init: Error al configurar el controlador de la señal TERM/INIT"
+
+#: daemon/slave.c:120
+msgid "gdm_slave_init: Error setting up CHLD signal handler"
+msgstr "gdm_slave_init: Error al configurar el controlador de la señal CHLD"
+
+#: daemon/slave.c:171
+msgid "gdm_slave_greeter: Can't init pipe to gdmgreeter"
+msgstr "gdm_slave_greeter: Imposible iniciar un tubo hacia gdmgreeter"
+
+#: daemon/slave.c:196
+#, c-format
+msgid "gdm_slave_greeter: Couldn't set groupid to %d"
+msgstr "gdm_slave_greeter: No pude configurar el grupo como gid %d"
+
+#: daemon/slave.c:199
+#, c-format
+msgid "gdm_slave_greeter: Couldn't set userid to %d"
+msgstr "gdm_slave_greeter: No pude configurar el usuario como uid %d"
+
+#: daemon/slave.c:209
+#, c-format
+msgid "gdm_slave_greeter: Error starting greeter on display %s"
+msgstr "gdm_slave_greeter: Error al lanzar la ventana de bienvenida en %s"
+
+#: daemon/slave.c:212
+msgid "gdm_slave_greeter: Can't fork gdmgreeter process"
+msgstr "gdm_slave_greeter: Imposible hacer un fork para el proceso gdmgreeter"
+
+#: daemon/slave.c:280
+#, c-format
+msgid "gdm_slave_session_init: User '%s' not found. Aborting."
+msgstr ""
+"gdm_slave_session_init: No se encuentró ningún usuario '%s'. Abortando."
+
+#: daemon/slave.c:299
+msgid ""
+"gdm_slave_session_init: Execution of PreSession script returned > 0. "
+"Aborting."
+msgstr ""
+"gdm_slave_session_init: La ejecución del script de Pre-sesión devolvió > 0. "
+"Abortando."
+
+#: daemon/slave.c:304
+msgid "gdm_slave_session_init: Error forking user session"
+msgstr ""
+"gdm_slave_session_init: Error al hacer un fork para la sesión del usuario"
+
+#: daemon/slave.c:312
+#, c-format
+msgid "gdm_slave_session_init: Could not setgid %d. Aborting."
+msgstr "gdm_slave_session_init: No pude hacer un setgid %d. Abortando"
+
+#: daemon/slave.c:315
+#, c-format
+msgid "gdm_slave_session_init: initgroups() failed for %s. Aborting."
+msgstr "gdm_slave_session_init: Falló initgroups() para %s. Abortando."
+
+#: daemon/slave.c:318
+#, c-format
+msgid "gdm_slave_session_init: Could not become %s. Aborting."
+msgstr "gdm_slave_session_init: No pude cambiarme en %s. Abortando."
+
+#: daemon/slave.c:373
+#, c-format
+msgid "gdm_slave_session_init: Could not start session `%s'"
+msgstr "gdm_slave_session_init: No pude lanzar la sesión `%s'"
+
+#: daemon/slave.c:547
+#, c-format
+msgid "gdm_slave_windows_kill_ioerror_handler: Fatal X error - Restarting %s"
+msgstr ""
+"gdm_slave_windows_kill_ioerror_handler: Error fatal de X - Reiniciando %s"
+
+#: daemon/slave.c:579
+msgid "gdm_slave_xsync_ping: Error setting up ALARM signal handler"
+msgstr ""
+"gdm_slave_xsync_ping: Error al configurar el controlador de la señal ALARM"
+
+#: daemon/verify.c:122 daemon/verify.c:185 gui/gdmgreeter.c:1363
+msgid "Login:"
+msgstr "Login:"
+
+#: daemon/verify.c:128
+msgid "Can't find /etc/pam.d/gdm!"
+msgstr "¡No se encuentra ningún /etc/pam.d/gdm!"
+
+#: daemon/verify.c:132
+#, c-format
+msgid "Can't set PAM_TTY=%s"
+msgstr "Imposible de definir PAM_TTY=%s"
+
+#: daemon/verify.c:137 daemon/verify.c:189
+#, c-format
+msgid "Couldn't authenticate %s"
+msgstr "No pude autentificar a %s"
+
+#: daemon/verify.c:142
+#, c-format
+msgid "Couldn't set acct. mgmt for %s"
+msgstr "No pude configurar la gestión de cuentas para %s"
+
+#: daemon/verify.c:147
+#, c-format
+msgid "Couldn't set credentials for %s"
+msgstr "No pude configurar las credenciales para %s"
+
+#: daemon/verify.c:152
+#, c-format
+msgid "Couldn't open session for %s"
+msgstr "No pude abrir una sesión para %s"
+
+#: daemon/verify.c:192
+msgid "User unknown"
+msgstr ""
+
+#: daemon/verify.c:208 gui/gdmgreeter.c:1369
+msgid "Password:"
+msgstr "Contraseña:"
+
+#: daemon/verify.c:213
+msgid "Incorrect password"
+msgstr ""
+
+#: daemon/xdmcp.c:172
+#, c-format
+msgid "gdm_xdmcp_init: Could not get server hostname: %s!"
+msgstr "gdm_xdmcp_init: ¡No pude obtener el nombre del servidor: %s!"
+
+#: daemon/xdmcp.c:183
+msgid "gdm_xdmcp_init: Could not create socket!"
+msgstr "gdm_xdmcp_init: ¡No pude crear el zócalo!"
+
+#: daemon/xdmcp.c:190
+msgid "gdm_xdmcp_init: Could not bind to XDMCP socket!"
+msgstr "gdm_xdmcp_init: ¡No pude conectarme al zócalo XDMCP!"
+
+#: daemon/xdmcp.c:225
+msgid "gdm_xdmcp_decode: Could not create XDMCP buffer!"
+msgstr "gdm_xdmcp_decode: ¡No pude crear un buffer XDMCP!"
+
+#: daemon/xdmcp.c:230
+msgid "gdm_xdmcp_decode: Could not read XDMCP header!"
+msgstr "gdm_xdmcp_decode: ¡No pude leer la cabecera XDMCP!"
+
+#: daemon/xdmcp.c:235
+msgid "gdm_xdmcp_decode: Incorrect XDMCP version!"
+msgstr "gdm_xdmcp_decode: ¡Versión de XDMCP incorrecta!"
+
+#: daemon/xdmcp.c:271
+#, c-format
+msgid "gdm_xdmcp_decode_packet: Unknown opcode from host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:289
+msgid "gdm_xdmcp_query: Could not extract authlist from packet"
+msgstr ""
+
+#: daemon/xdmcp.c:300
+msgid "gdm_xdmcp_query: Error in checksum"
+msgstr ""
+
+#: daemon/xdmcp.c:323
+msgid "GNOME"
+msgstr "GNOME"
+
+#: daemon/xdmcp.c:347
+#, c-format
+msgid "Denied XDMCP query from host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:349
+msgid "Display not authorized to connect"
+msgstr "Display no autorizado a conectarse"
+
+#: daemon/xdmcp.c:382
+#, c-format
+msgid "gdm_xdmcp_handle_request: Got REQUEST from banned host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:389
+msgid "gdm_xdmcp_handle_request: Could not read Display Number"
+msgstr ""
+
+#: daemon/xdmcp.c:395
+msgid "gdm_xdmcp_handle_request: Could not read Connection Type"
+msgstr ""
+
+#: daemon/xdmcp.c:401
+msgid "gdm_xdmcp_handle_request: Could not read Client Address"
+msgstr ""
+
+#: daemon/xdmcp.c:407
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Names"
+msgstr ""
+
+#: daemon/xdmcp.c:413
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Data"
+msgstr ""
+
+#: daemon/xdmcp.c:419
+msgid "gdm_xdmcp_handle_request: Could not read Authorization List"
+msgstr ""
+
+#: daemon/xdmcp.c:430
+msgid "gdm_xdmcp_handle_request: Could not read Manufacturer ID"
+msgstr ""
+
+#: daemon/xdmcp.c:448
+#, c-format
+msgid "gdm_xdmcp_handle_request: Failed checksum from %s"
+msgstr ""
+
+#: daemon/xdmcp.c:566
+#, c-format
+msgid "gdm_xdmcp_handle_manage: Got Manage from banned host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:573
+msgid "gdm_xdmcp_handle_manage: Could not read Session ID"
+msgstr ""
+
+#: daemon/xdmcp.c:579
+msgid "gdm_xdmcp_handle_manage: Could not read Display Number"
+msgstr ""
+
+#: daemon/xdmcp.c:588
+msgid "gdm_xdmcp_manage: Could not read Display Class"
+msgstr ""
+
+#: daemon/xdmcp.c:607
+#, c-format
+msgid "gdm_xdmcp_handle_manage: Could not open logfile for display %s!"
+msgstr ""
+
+#: daemon/xdmcp.c:679
+#, c-format
+msgid "gdm_xdmcp_handle_keepalive: Got KEEPALIVE from banned host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:686
+msgid "gdm_xdmcp_handle_keepalive: Could not read Display Number"
+msgstr ""
+
+#: daemon/xdmcp.c:692
+msgid "gdm_xdmcp_handle_keepalive: Could not read Session ID"
+msgstr ""
+
+#: gui/gdmchooser.c:336
+#, fuzzy, c-format
+msgid "gdm_chooser_parse_config: No configuration file: %s. Aborting."
+msgstr ""
+"gdm_greeter_parse_config: Ningún archivo de configuración: %s. Abortando."
+
+#: gui/gdmchooser.c:447
+#, fuzzy, c-format
+msgid "Can't open default host icon: %s"
+msgstr "No pude abrir una sesión para %s"
+
+#. Buttons
+#: gui/gdmchooser.c:512
+msgid "Connect"
+msgstr ""
+
+#: gui/gdmchooser.c:519
+msgid "Rescan"
+msgstr ""
+
+#: gui/gdmchooser.c:525
+msgid "Cancel"
+msgstr ""
+
+#: gui/gdmchooser.c:576 gui/gdmgreeter.c:1672 gui/gdmlogin.c:1102
+msgid "main: Error setting up HUP signal handler"
+msgstr "main: Error al configurar el controlador de la señal HUP"
+
+#: gui/gdmchooser.c:579 gui/gdmgreeter.c:1675 gui/gdmlogin.c:1105
+msgid "main: Error setting up INT signal handler"
+msgstr "main: Error al configurar el controlador de la señal INT"
+
+#: gui/gdmchooser.c:582 gui/gdmgreeter.c:1678 gui/gdmlogin.c:1108
+msgid "main: Error setting up TERM signal handler"
+msgstr "main: Error al configurar el controlador de la señal TERM"
+
+#: gui/gdmgreeter.c:155
+msgid "Gnome Display Manager"
+msgstr "Gestor de Display de Gnome"
+
+#: gui/gdmgreeter.c:157
+msgid "Copyright Martin K. Petersen (C) 1998, 1999"
+msgstr "Copyright Martin K. Petersen © 1998, 1999"
+
+#: gui/gdmgreeter.c:159 gui/gdmlogin.c:328
+msgid ""
+"gdm manages local and remote displays and provides the user with a login "
+"window."
+msgstr ""
+"gdm se ocupa de la gestión de pantallas locales y remotas y proporciona al "
+"usuario una ventana de login."
+
+#: gui/gdmgreeter.c:194 gui/gdmlogin.c:271
+msgid "gdm_parse_enriched_string: String too long!"
+msgstr "gdm_parse_enriched_string: ¡Cadena demasiado larga!"
+
+#: gui/gdmgreeter.c:195 gui/gdmlogin.c:272
+msgid "Welcome to "
+msgstr "Bientenido a"
+
+#: gui/gdmgreeter.c:199 gui/gdmlogin.c:276
+msgid "gdm_parse_enriched_string: Could not malloc temporary buffer!"
+msgstr ""
+"gdm_parse_enriched_string: ¡No pude hacer un malloc para un buffer temporal!"
+
+#: gui/gdmgreeter.c:273
+msgid "Logo not found. No image will be displayed!"
+msgstr "No se encuentra el logotipo. ¡Ninguna imagen sera usada!"
+
+#: gui/gdmgreeter.c:299
+#, c-format
+msgid "gdm_greeter_parse_config: No configuration file: %s. Aborting."
+msgstr ""
+"gdm_greeter_parse_config: Ningún archivo de configuración: %s. Abortando."
+
+#: gui/gdmgreeter.c:323 gui/gdmlogin.c:403
+#, c-format
+msgid "messages/welcome=Welcome to %h"
+msgstr "messages/welcome=Bienvenido a %h"
+
+#: gui/gdmgreeter.c:424 gui/gdmlogin.c:527 gui/gdmlogin.c:557
+#, c-format
+msgid ""
+"You have chosen %s for this session, but your default setting is %s.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Ha escogido %s para esta sesión, pero su sesión por omisión es %s.\n"
+"¿Desea hacer de %s su sesión por omisión a partir de ahora?"
+
+#: gui/gdmgreeter.c:432
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Su tipo de sesión anterior %s no está disponible en esta máquina.\n"
+"¿Desea hacer de %s su sesión por omisión a partir de ahora?"
+
+#: gui/gdmgreeter.c:440
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"You will be logged in using the %s environment."
+msgstr ""
+"Su tipo de sesión %s no está instalada en esta máquina.\n"
+"Será iniciada con el entorno %s."
+
+#: gui/gdmgreeter.c:453
+#, c-format
+msgid ""
+"You have chosen the language %s for this session, but your default setting "
+"is %s.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+"Escogió el idioma %s para su sesión, pero su valor normal es %s\n"
+"¿Desea que %s sea el idioma por omisión para sus sesiones futuras?"
+
+#: gui/gdmgreeter.c:461
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+"El idioma anterior %s no está instalado en esta máquina.\n"
+"¿Desea hacer de %s el idioma por omisión para sus sesiones futuras?"
+
+#: gui/gdmgreeter.c:469
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Your environment will be %s."
+msgstr ""
+"Su idioma anterior %s no está instalado en esta máquina\n"
+"Su entorno será %s."
+
+#: gui/gdmgreeter.c:500
+msgid "Invalid username or password!"
+msgstr "¡Nombre de usuario o contraseña inválidos!"
+
+#: gui/gdmgreeter.c:526 gui/gdmlogin.c:354
+msgid "Are you sure you want to reboot the machine?"
+msgstr "¿Está seguro que quiere reiniciar el sistema?"
+
+#: gui/gdmgreeter.c:555 gui/gdmlogin.c:366
+msgid "Are you sure you want to halt the machine?"
+msgstr "¿Está seguro que quiere apagar el sistema?"
+
+#: gui/gdmgreeter.c:812
+msgid "gdm_greeter_session_init: Session script directory not found!"
+msgstr ""
+"gdm_greeter_session_init: ¡No se encuentra el directorio de los scripts de "
+"sesión!"
+
+#: gui/gdmgreeter.c:865 gui/gdmlogin.c:694
+msgid "No session scripts found. Aborting!"
+msgstr "¡No se encuentran scripts de sesión. Abortando!"
+
+#: gui/gdmgreeter.c:869 gui/gdmlogin.c:698
+#, c-format
+msgid "No default session link found. Using %s.\n"
+msgstr "No se encuentra un lazo de sesión por omisión. Usando %s.\n"
+
+#. Login button
+#: gui/gdmgreeter.c:1029
+msgid "Login"
+msgstr "Login"
+
+#. Init sessions menu
+#: gui/gdmgreeter.c:1041
+msgid "Sessions"
+msgstr "Sesiones"
+
+#. Language selection support
+#: gui/gdmgreeter.c:1048
+msgid "Languages"
+msgstr "Idiomas"
+
+#: gui/gdmgreeter.c:1058 gui/gdmlogin.c:960
+msgid "Reboot..."
+msgstr "Reiniciar..."
+
+#: gui/gdmgreeter.c:1064 gui/gdmlogin.c:966
+msgid "Halt..."
+msgstr "Detener..."
+
+#: gui/gdmgreeter.c:1071
+msgid "Suspend"
+msgstr "Suspender"
+
+#: gui/gdmgreeter.c:1078 gui/gdmlogin.c:972
+msgid "System"
+msgstr "Sistema"
+
+#: gui/gdmgreeter.c:1086 gui/gdmlogin.c:986
+#, c-format
+msgid "Can't open icon file: %s. Suspending iconify feature!"
+msgstr ""
+"¡Imposible de abrir el archivo de ícono: %s. Suspendiendo la posibilidad de "
+"iconificar!"
+
+#: gui/gdmgreeter.c:1090 gui/gdmlogin.c:990
+msgid "Iconify"
+msgstr "Iconificar"
+
+#. Option button
+#: gui/gdmgreeter.c:1099
+msgid "Options..."
+msgstr "Opciones..."
+
+#: gui/gdmgreeter.c:1531
+#, c-format
+msgid "Can't open NofaceImageFile: %s. Suspending face browser!"
+msgstr ""
+"¡Imposible de abrir NofaceImageFile: %s. Suspendiendo el visualizador de "
+"fotos!"
+
+#: gui/gdmgreeter.c:1686
+msgid "main: Error setting up USR1 signal handler"
+msgstr "main: Error al configurar el controlador de la señal USR1"
+
+#: gui/gdmgreeter.c:1694
+msgid "main: Error setting up USR2 signal handler"
+msgstr "main: Error al configurar el controlador de la señal USR2"
+
+#: gui/gdmlogin.c:382
+#, fuzzy, c-format
+msgid "gdm_login_parse_config: No configuration file: %s. Aborting."
+msgstr ""
+"gdm_greeter_parse_config: Ningún archivo de configuración: %s. Abortando."
+
+#: gui/gdmlogin.c:508
+#, fuzzy, c-format
+msgid ""
+"Your preferred session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Su tipo de sesión anterior %s no está disponible en esta máquina.\n"
+"¿Desea hacer de %s su sesión por omisión a partir de ahora?"
+
+#: gui/gdmlogin.c:616
+#, c-format
+msgid "%s session selected"
+msgstr ""
+
+#: gui/gdmlogin.c:632 gui/gdmlogin.c:723
+msgid "Last"
+msgstr ""
+
+#: gui/gdmlogin.c:647
+#, fuzzy
+msgid "gdm_login_session_init: Session script directory not found!"
+msgstr ""
+"gdm_greeter_session_init: ¡No se encuentra el directorio de los scripts de "
+"sesión!"
+
+#: gui/gdmlogin.c:709
+#, c-format
+msgid "%s language selected"
+msgstr ""
+
+#: gui/gdmlogin.c:736
+msgid "A-M"
+msgstr ""
+
+#: gui/gdmlogin.c:742
+msgid "N-Z"
+msgstr ""
+
+#: gui/gdmlogin.c:748
+msgid "Other"
+msgstr ""
+
+#: gui/gdmlogin.c:946
+#, fuzzy
+msgid "Session"
+msgstr "Sesiones"
+
+#: gui/gdmlogin.c:953
+#, fuzzy
+msgid "Language"
+msgstr "Idiomas"
+
+#: gui/gdmlogin.c:979
+msgid "Host chooser"
+msgstr ""
+
+#, fuzzy
+#~ msgid "gdm_server_usr1_handler: Could not open display %s"
+#~ msgstr "gdm_slave_windows_kill: No pude abrir el display %s"
+
+#, fuzzy
+#~ msgid "gdm_display_dispose: Closing display %s"
+#~ msgstr "gdm_display_dispose: Disponiendo %s"
+
+#~ msgid "gdm_display_dispose: Disposing %s"
+#~ msgstr "gdm_display_dispose: Disponiendo %s"
+
+#~ msgid "gdm_display_manage: Managing %s"
+#~ msgstr "gdm_display_manage: controlando %s"
+
+#~ msgid "gdm_display_manage: Forked slave: %d...\n"
+#~ msgstr "gdm_display_manage: esclavo creado: %d\n"
+
+#~ msgid "gdm_child_action: %s"
+#~ msgstr "gdm_child_action: %s"
+
+#~ msgid "gdm_child_action: Server process returned unknown status %d"
+#~ msgstr ""
+#~ "gdm_child_action: El proceso servidor regreso un estado desconocido: %d"
+
+#, fuzzy
+#~ msgid "gdm_child_action: Slave process returned unknown status %d"
+#~ msgstr "gdm_child_action: Proceso esclavo regreso un estaod desconocido"
+
+#~ msgid "gdm_child_handler: child %d returned %d"
+#~ msgstr "gdm_child_handler: hijo %d regreso %d"
+
+#~ msgid "gdm_display_unmanage: Stopping %s"
+#~ msgstr "gdm_display_unmanage: Deteniendo %s"
+
+#~ msgid "gdm_term_handler: Got TERM/INT. Going down!"
+#~ msgstr "gdm_term_handler: Recibí un TERM/INT. Deteniendonos!"
+
+#~ msgid "gdm_main: Here we go..."
+#~ msgstr "gdm_main: allá vamos..."
+
+#~ msgid "gdm_auth_secure_display: Securing %s"
+#~ msgstr "gdm_auth_secure_display: Asegurando %s"
+
+#~ msgid "gdm_auth_user_add: Adding cookie to %s"
+#~ msgstr "gdm_auth_user_add: Añadiendo cookie para %s"
+
+#~ msgid "gdm_auth_user_remove: Removing cookie from %s"
+#~ msgstr "gdm_auth_user_remove: Borrando cookia de %s"
+
+#~ msgid "gdm_slave_start: Starting slave process for %s"
+#~ msgstr "gdm_slave_start: Lanzando proceso esclavo para %s"
+
+#~ msgid "gdm_slave_start: Opening display %s"
+#~ msgstr "gdm_slave_start: Abriendo el display %s"
+
+#~ msgid "gdm_slave_greeter: Running greeter on %s"
+#~ msgstr "gdm_slave_greeter: Lanzando la ventana de bienvenida en %s"
+
+#~ msgid "gdm_slave_greeter: Greeter on pid %d"
+#~ msgstr "gdm_slave_greeter: Ventana de bienvenida con pid %d"
+
+#~ msgid "gdm_slave_greeter: No command followed STX"
+#~ msgstr "gdm_slave_greeter: Ningún comando siguió STX"
+
+#~ msgid "gdm_slave_greeter: Insufficient data from greeter in pipe"
+#~ msgstr ""
+#~ "gdm_slave_greeter: Datos insuficientes de la ventana de bienvenida en el tubo"
+
+#~ msgid "gdm_slave_get_opts: Insufficient data from greeter in pipe"
+#~ msgstr ""
+#~ "gdm_slave_get_opts: Datos insuficientes de la ventana de bienvenida en el "
+#~ "tubo"
+
+#~ msgid "gdm_slave_session_start: %s on %s"
+#~ msgstr "gdm_slave_session_start: %s en %s"
+
+#~ msgid "gdm_slave_session_stop: %s on %s"
+#~ msgstr "gdm_slave_session_stop: %s en %s"
+
+#~ msgid "gdm_slave_session_cleanup: %s on %s"
+#~ msgstr "gdm_slave_session_cleanup: %s en %s"
+
+#~ msgid "gdm_slave_session_cleanup: Running post session script"
+#~ msgstr "gdm_slave_session_cleanup: Corriendo script de post-sesión"
+
+#~ msgid "gdm_slave_session_cleanup: Killing windows"
+#~ msgstr "gdm_slave_session_cleanup: Matando las ventanas"
+
+#~ msgid "gdm_slave_term_handler: %s got TERM signal"
+#~ msgstr "gdm_slave_term_handler: %s recibió la señal TERM"
+
+#~ msgid "gdm_slave_term_handler: Whacking greeter"
+#~ msgstr "gdm_slave_term_handler: Despertando la ventana de bienvenida"
+
+#~ msgid "gdm_slave_term_handler: Whacking client connections"
+#~ msgstr "gdm_slave_term_handler: Despertando las conexiones clientes"
+
+#~ msgid "gdm_slave_child_handler: %d died"
+#~ msgstr "gdm_slave_child_handler: murió %d"
+
+#~ msgid "gdm_slave_child_handler: %d returned %d"
+#~ msgstr "gdm_slave_child_handler: %d devolvió %d"
+
+#~ msgid "gdm_slave_windows_kill: Killing windows on %s"
+#~ msgstr "gdm_slave_windows_kill: Matando las ventanas en %s"
+
+#~ msgid "gdm_slave_windows_kill: Killing child 0x%x"
+#~ msgstr "gdm_slave_windows_kill: Matando el hijo 0x%x"
+
+#~ msgid "gdm_slave_xioerror_handler: I/O error for display %s"
+#~ msgstr "gdm_slave_xioerror_handler: Error de E/S en el display %s"
+
+#~ msgid "gdm_slave_xsync_handler: Xping failed for display %s"
+#~ msgstr "gdm_slave_xsync_handler: Falló Xping para el display %s"
+
+#~ msgid "gdm_slave_xsync_ping: Pinging %s"
+#~ msgstr "gdm_slave_xsync_ping: Haciendo un ping a %s"
+
+#~ msgid "gdm_slave_xsync_ping: Pinging %s returned %d"
+#~ msgstr "gdm_slave_xsync_ping: El ping a %s devolvió %d"
diff --git a/po/fr.po b/po/fr.po
new file mode 100644
index 00000000..79962558
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,1012 @@
+# gdm fr.po
+# Copyright (C) 1998 Free Software Foundation, Inc.
+# Vincent Renardias <vincent@debian.org>, 1998.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gdm VERSION\n"
+"POT-Creation-Date: 1999-04-08 02:02+0200\n"
+"PO-Revision-Date: 1998-09-12 21:08+0200\n"
+"Last-Translator: Vincent Renardias <vincent@debian.org>\n"
+"Language-Team: Vincent Renardias <vincent@debian.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: daemon/gdm.c:136
+#, c-format
+msgid "gdm_config_parse: No configuration file: %s. Aborting."
+msgstr "gdm_config_parse: Pas de fichier de configuration: %s. Abandon."
+
+#: daemon/gdm.c:177
+msgid "gdm_config_parse: No greeter specified and default not found."
+msgstr ""
+
+#: daemon/gdm.c:189
+msgid "gdm_config_parse: No authdir specified and default not found."
+msgstr ""
+
+#: daemon/gdm.c:207
+msgid ""
+"gdm_config_parse: No sessions directory specified and default not found."
+msgstr ""
+
+#: daemon/gdm.c:219
+#, fuzzy
+msgid "gdm_config_parse: Invalid server line in config file. Ignoring!"
+msgstr "gdm_config_parse: Pas de fichier de configuration: %s. Abandon."
+
+#: daemon/gdm.c:225
+#, fuzzy
+msgid ""
+"gdm_config_parse: Xdmcp disabled and no local servers defined. Aborting!"
+msgstr "gdm_config_parse: Pas de serveurs locaux définis."
+
+#: daemon/gdm.c:230
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm user (%s). Aborting!"
+msgstr ""
+"gdm_config_parse: Impossible de trouver l'utilisateur gdm (%s). Abandon!"
+
+#: daemon/gdm.c:235
+#, fuzzy
+msgid "gdm_config_parse: The gdm user should not be root. Aborting!"
+msgstr "gdm_config_parse: Le répertoire Authdir %s n'existe pas. Abandon."
+
+#: daemon/gdm.c:240
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm group (%s). Aborting!"
+msgstr "gdm_config_parse: Impossible de trouver le groupe gdm (%s). Abandon!"
+
+#: daemon/gdm.c:246
+#, fuzzy
+msgid "gdm_config_parse: The gdm group should not be root. Aborting!"
+msgstr "gdm_config_parse: Impossible de trouver le groupe gdm (%s). Abandon!"
+
+#: daemon/gdm.c:253
+#, c-format
+msgid "gdm_config_parse: Authdir %s does not exist. Aborting."
+msgstr "gdm_config_parse: Le répertoire Authdir %s n'existe pas. Abandon."
+
+#: daemon/gdm.c:256
+#, c-format
+msgid "gdm_config_parse: Authdir %s is not a directory. Aborting."
+msgstr "gdm_config_parse: Authdir %s n'est pas un répertoire. Abandon."
+
+#: daemon/gdm.c:259
+#, fuzzy, c-format
+msgid ""
+"gdm_config_parse: Authdir %s is not owned by user %s, group %s. Aborting."
+msgstr ""
+"gdm_config_parse: l'utilisateur gdm ne peux pas accéder au répertoire "
+"d'authentification %s. Abandon."
+
+#: daemon/gdm.c:262
+#, fuzzy, c-format
+msgid ""
+"gdm_config_parse: Authdir %s has wrong permissions. Should be 750. Aborting."
+msgstr "gdm_config_parse: Pas de fichier de configuration: %s. Abandon."
+
+#: daemon/gdm.c:318
+#, fuzzy, c-format
+msgid "gdm_display_manage: Failed forking gdm slave process for %d"
+msgstr "gdm_display_run: Echec du lancement d'un processus esclave pour %d"
+
+#: daemon/gdm.c:397
+#, c-format
+msgid "gdm_child_action: Aborting display %s"
+msgstr ""
+
+#: daemon/gdm.c:402
+#, fuzzy
+msgid "gdm_child_action: Master rebooting..."
+msgstr "gdm_restart_slave: Redémarrage du maitre..."
+
+#: daemon/gdm.c:408
+#, fuzzy, c-format
+msgid "gdm_child_action: Reboot failed: %s"
+msgstr "gdm_restart_slave: Echec du redémarrage: %s"
+
+#: daemon/gdm.c:412
+#, fuzzy
+msgid "gdm_child_action: Master halting..."
+msgstr "gdm_restart_slave: Arrêt du maitre..."
+
+#: daemon/gdm.c:418
+#, fuzzy, c-format
+msgid "gdm_child_action: Halt failed: %s"
+msgstr "gdm_restart_slave: Echec de l'arrêt: %s"
+
+#: daemon/gdm.c:512
+msgid "gdm_daemonify: fork() failed!"
+msgstr "gdm_daemonify: echec de fork()!"
+
+#: daemon/gdm.c:515
+#, c-format
+msgid "gdm_daemonify: setsid() failed: %s!"
+msgstr "gdm_daemonify: echec de setid(): %s!"
+
+#: daemon/gdm.c:540
+msgid "Only root wants to run gdm\n"
+msgstr ""
+
+#: daemon/gdm.c:558
+msgid ""
+"gdm already running. Aborting!\n"
+"\n"
+msgstr "gdm est déjà lancé. Abandon!\n"
+
+#: daemon/gdm.c:563
+#, fuzzy, c-format
+msgid ""
+"According to %s, gdm was already running (%d),\n"
+"but seems to have been murdered mysteriously.\n"
+msgstr ""
+"gdm est déjà lancé (%d) mais semble avoir été mystérieusement assassiné.\n"
+
+#: daemon/gdm.c:584
+msgid "gdm_main: Error setting up TERM signal handler"
+msgstr ""
+"gdm_main: Erreur lors de la configuration du gestionnaire du signal TERM"
+
+#: daemon/gdm.c:587
+msgid "gdm_main: Error setting up INT signal handler"
+msgstr ""
+"gdm_main: Erreur lors de la configuration du gestionnaire du signal INT"
+
+#: daemon/gdm.c:595
+msgid "gdm_main: Error setting up CHLD signal handler"
+msgstr ""
+"gdm_main: Erreur lors de la configuration du gestionnaire du signal CHLD"
+
+#: daemon/auth.c:62
+#, c-format
+msgid "gdm_auth_secure_display: Could not unlink %s file: %s"
+msgstr "gdm_auth_secure_display: Impossible d'effacer le fichier %s"
+
+#: daemon/auth.c:73
+#, c-format
+msgid ""
+"gdm_auth_secure_display: Error starting xauth process: %s. Running insecure!"
+msgstr ""
+
+#: daemon/auth.c:77
+msgid "gdm_auth_secure_display: Error forking xauth process. Running insecure!"
+msgstr ""
+
+#: daemon/auth.c:109
+#, c-format
+msgid "gdm_auth_user_add: Error starting xauth process: %s"
+msgstr ""
+
+#: daemon/auth.c:113
+msgid "gdm_auth_user_add: Error forking xauth process."
+msgstr ""
+
+#: daemon/auth.c:143
+#, c-format
+msgid "gdm_auth_user_remove: Error starting xauth process: %s"
+msgstr ""
+
+#: daemon/auth.c:147
+msgid "gdm_auth_user_remove: Error forking xauth process."
+msgstr ""
+
+#: daemon/filecheck.c:50 daemon/filecheck.c:83
+#, c-format
+msgid "%s: %s is not owned by uid %d. Skipping."
+msgstr ""
+
+#: daemon/filecheck.c:57
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 755. Skipping."
+msgstr ""
+
+#: daemon/filecheck.c:76
+#, c-format
+msgid "%s: %s is not a regular file. Skipping."
+msgstr ""
+
+#: daemon/filecheck.c:90
+#, c-format
+msgid "%s: %s is writable by group. Should be 644. Skipping."
+msgstr ""
+
+#: daemon/filecheck.c:97
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 644. Skipping."
+msgstr ""
+
+#: daemon/filecheck.c:104
+#, c-format
+msgid "%s: %s is bigger than sysadmin specified maximum file size. Skipping."
+msgstr ""
+
+#: daemon/misc.c:121
+#, c-format
+msgid "gdm_exec_script: Failed starting: %s"
+msgstr ""
+
+#: daemon/misc.c:125
+#, fuzzy
+msgid "gdm_exec_script: Can't fork script process!"
+msgstr "gdm_slave_server_init: Impossible de forker le processus Xserver!"
+
+#: daemon/misc.c:153
+#, c-format
+msgid "gdm_exec_command: Failed starting: %s"
+msgstr ""
+
+#: daemon/misc.c:157
+#, fuzzy
+msgid "gdm_exec_command: Can't fork process!"
+msgstr "gdm_slave_server_init: Impossible de forker le processus Xserver!"
+
+#: daemon/server.c:82 daemon/server.c:213
+#, fuzzy
+msgid "gdm_server_start: Error setting up USR1 signal handler"
+msgstr ""
+"gdm_slave_server_start: Erreur lors de la configuration du gestionnaire du "
+"signal USR1"
+
+#: daemon/server.c:99
+#, fuzzy, c-format
+msgid "gdm_server_start: Could not open logfile for display %s!"
+msgstr "Impossible d'ouvrir le fichier d'historique pour l'affichage %s!"
+
+#: daemon/server.c:129
+#, fuzzy
+msgid "gdm_server_start: Error setting USR1 to SIG_IGN"
+msgstr ""
+"gdm_slave_server_start: Erreur lors de la configuration du gestionnaire du "
+"signal USR1"
+
+#: daemon/server.c:146
+#, fuzzy, c-format
+msgid "gdm_server_start: Xserver not found: %s"
+msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#: daemon/server.c:152
+#, fuzzy
+msgid "gdm_server_start: Can't fork Xserver process!"
+msgstr "gdm_slave_server_init: Impossible de forker le processus Xserver!"
+
+#: daemon/server.c:178
+#, fuzzy, c-format
+msgid "gdm_server_stop: Could not unlink auth file: %s!"
+msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#: daemon/server.c:237
+#, fuzzy
+msgid "gdm_server_restart: Error setting up ALARM signal handler"
+msgstr ""
+"gdm_slave_server_start: Erreur lors de la configuration du gestionnaire du "
+"signal USR1"
+
+#: daemon/slave.c:112
+msgid "gdm_slave_init: Error setting up TERM/INT signal handler"
+msgstr ""
+
+#: daemon/slave.c:120
+msgid "gdm_slave_init: Error setting up CHLD signal handler"
+msgstr ""
+
+#: daemon/slave.c:171
+#, fuzzy
+msgid "gdm_slave_greeter: Can't init pipe to gdmgreeter"
+msgstr "gdm_slave_server_init: Impossible de forker le processus Xserver!"
+
+#: daemon/slave.c:196
+#, fuzzy, c-format
+msgid "gdm_slave_greeter: Couldn't set groupid to %d"
+msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#: daemon/slave.c:199
+#, fuzzy, c-format
+msgid "gdm_slave_greeter: Couldn't set userid to %d"
+msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#: daemon/slave.c:209
+#, fuzzy, c-format
+msgid "gdm_slave_greeter: Error starting greeter on display %s"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/slave.c:212
+#, fuzzy
+msgid "gdm_slave_greeter: Can't fork gdmgreeter process"
+msgstr "gdm_slave_server_init: Impossible de forker le processus Xserver!"
+
+#: daemon/slave.c:280
+#, c-format
+msgid "gdm_slave_session_init: User '%s' not found. Aborting."
+msgstr ""
+
+#: daemon/slave.c:299
+#, fuzzy
+msgid ""
+"gdm_slave_session_init: Execution of PreSession script returned > 0. "
+"Aborting."
+msgstr "gdm_slave_session_init: Fin de la session!"
+
+#: daemon/slave.c:304
+msgid "gdm_slave_session_init: Error forking user session"
+msgstr ""
+
+#: daemon/slave.c:312
+#, fuzzy, c-format
+msgid "gdm_slave_session_init: Could not setgid %d. Aborting."
+msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#: daemon/slave.c:315
+#, fuzzy, c-format
+msgid "gdm_slave_session_init: initgroups() failed for %s. Aborting."
+msgstr "gdm_slave_session_init: Fin de la session!"
+
+#: daemon/slave.c:318
+#, c-format
+msgid "gdm_slave_session_init: Could not become %s. Aborting."
+msgstr ""
+
+#: daemon/slave.c:373
+#, c-format
+msgid "gdm_slave_session_init: Could not start session `%s'"
+msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#: daemon/slave.c:547
+#, c-format
+msgid "gdm_slave_windows_kill_ioerror_handler: Fatal X error - Restarting %s"
+msgstr ""
+
+#: daemon/slave.c:579
+#, fuzzy
+msgid "gdm_slave_xsync_ping: Error setting up ALARM signal handler"
+msgstr ""
+"gdm_main: Erreur lors de la configuration du gestionnaire du signal TERM"
+
+#: daemon/verify.c:122 daemon/verify.c:185 gui/gdmgreeter.c:1363
+msgid "Login:"
+msgstr ""
+
+#: daemon/verify.c:128
+msgid "Can't find /etc/pam.d/gdm!"
+msgstr ""
+
+#: daemon/verify.c:132
+#, c-format
+msgid "Can't set PAM_TTY=%s"
+msgstr ""
+
+#: daemon/verify.c:137 daemon/verify.c:189
+#, c-format
+msgid "Couldn't authenticate %s"
+msgstr ""
+
+#: daemon/verify.c:142
+#, c-format
+msgid "Couldn't set acct. mgmt for %s"
+msgstr ""
+
+#: daemon/verify.c:147
+#, c-format
+msgid "Couldn't set credentials for %s"
+msgstr ""
+
+#: daemon/verify.c:152
+#, fuzzy, c-format
+msgid "Couldn't open session for %s"
+msgstr "Impossible d'ouvrir le fichier d'historique pour l'affichage %s!"
+
+#: daemon/verify.c:192
+msgid "User unknown"
+msgstr ""
+
+#: daemon/verify.c:208 gui/gdmgreeter.c:1369
+msgid "Password:"
+msgstr ""
+
+#: daemon/verify.c:213
+msgid "Incorrect password"
+msgstr ""
+
+#: daemon/xdmcp.c:172
+#, fuzzy, c-format
+msgid "gdm_xdmcp_init: Could not get server hostname: %s!"
+msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#: daemon/xdmcp.c:183
+#, fuzzy
+msgid "gdm_xdmcp_init: Could not create socket!"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:190
+msgid "gdm_xdmcp_init: Could not bind to XDMCP socket!"
+msgstr ""
+
+#: daemon/xdmcp.c:225
+msgid "gdm_xdmcp_decode: Could not create XDMCP buffer!"
+msgstr ""
+
+#: daemon/xdmcp.c:230
+msgid "gdm_xdmcp_decode: Could not read XDMCP header!"
+msgstr ""
+
+#: daemon/xdmcp.c:235
+msgid "gdm_xdmcp_decode: Incorrect XDMCP version!"
+msgstr ""
+
+#: daemon/xdmcp.c:271
+#, c-format
+msgid "gdm_xdmcp_decode_packet: Unknown opcode from host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:289
+#, fuzzy
+msgid "gdm_xdmcp_query: Could not extract authlist from packet"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:300
+msgid "gdm_xdmcp_query: Error in checksum"
+msgstr ""
+
+#: daemon/xdmcp.c:323
+msgid "GNOME"
+msgstr ""
+
+#: daemon/xdmcp.c:347
+#, c-format
+msgid "Denied XDMCP query from host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:349
+msgid "Display not authorized to connect"
+msgstr ""
+
+#: daemon/xdmcp.c:382
+#, c-format
+msgid "gdm_xdmcp_handle_request: Got REQUEST from banned host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:389
+#, fuzzy
+msgid "gdm_xdmcp_handle_request: Could not read Display Number"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:395
+#, fuzzy
+msgid "gdm_xdmcp_handle_request: Could not read Connection Type"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:401
+#, fuzzy
+msgid "gdm_xdmcp_handle_request: Could not read Client Address"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:407
+#, fuzzy
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Names"
+msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#: daemon/xdmcp.c:413
+#, fuzzy
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Data"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:419
+#, fuzzy
+msgid "gdm_xdmcp_handle_request: Could not read Authorization List"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:430
+#, fuzzy
+msgid "gdm_xdmcp_handle_request: Could not read Manufacturer ID"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:448
+#, c-format
+msgid "gdm_xdmcp_handle_request: Failed checksum from %s"
+msgstr ""
+
+#: daemon/xdmcp.c:566
+#, c-format
+msgid "gdm_xdmcp_handle_manage: Got Manage from banned host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:573
+#, fuzzy
+msgid "gdm_xdmcp_handle_manage: Could not read Session ID"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:579
+#, fuzzy
+msgid "gdm_xdmcp_handle_manage: Could not read Display Number"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:588
+#, fuzzy
+msgid "gdm_xdmcp_manage: Could not read Display Class"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:607
+#, fuzzy, c-format
+msgid "gdm_xdmcp_handle_manage: Could not open logfile for display %s!"
+msgstr "Impossible d'ouvrir le fichier d'historique pour l'affichage %s!"
+
+#: daemon/xdmcp.c:679
+#, c-format
+msgid "gdm_xdmcp_handle_keepalive: Got KEEPALIVE from banned host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:686
+#, fuzzy
+msgid "gdm_xdmcp_handle_keepalive: Could not read Display Number"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: daemon/xdmcp.c:692
+#, fuzzy
+msgid "gdm_xdmcp_handle_keepalive: Could not read Session ID"
+msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#: gui/gdmchooser.c:336
+#, fuzzy, c-format
+msgid "gdm_chooser_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_config_parse: Pas de fichier de configuration: %s. Abandon."
+
+#: gui/gdmchooser.c:447
+#, fuzzy, c-format
+msgid "Can't open default host icon: %s"
+msgstr "Impossible d'ouvrir le fichier d'historique pour l'affichage %s!"
+
+#. Buttons
+#: gui/gdmchooser.c:512
+msgid "Connect"
+msgstr ""
+
+#: gui/gdmchooser.c:519
+msgid "Rescan"
+msgstr ""
+
+#: gui/gdmchooser.c:525
+msgid "Cancel"
+msgstr ""
+
+#: gui/gdmchooser.c:576 gui/gdmgreeter.c:1672 gui/gdmlogin.c:1102
+msgid "main: Error setting up HUP signal handler"
+msgstr ""
+
+#: gui/gdmchooser.c:579 gui/gdmgreeter.c:1675 gui/gdmlogin.c:1105
+msgid "main: Error setting up INT signal handler"
+msgstr "main: Erreur lors de la configuration du gestionnaire du signal INT"
+
+#: gui/gdmchooser.c:582 gui/gdmgreeter.c:1678 gui/gdmlogin.c:1108
+msgid "main: Error setting up TERM signal handler"
+msgstr "main: Erreur lors de la configuration du gestionnaire du signal TERM"
+
+#: gui/gdmgreeter.c:155
+msgid "Gnome Display Manager"
+msgstr "Gestionnaire d'Affichage Gnome"
+
+#: gui/gdmgreeter.c:157
+#, fuzzy
+msgid "Copyright Martin K. Petersen (C) 1998, 1999"
+msgstr "Copyright Martin K. Petersen (C) 1998"
+
+#: gui/gdmgreeter.c:159 gui/gdmlogin.c:328
+msgid ""
+"gdm manages local and remote displays and provides the user with a login "
+"window."
+msgstr ""
+
+#: gui/gdmgreeter.c:194 gui/gdmlogin.c:271
+msgid "gdm_parse_enriched_string: String too long!"
+msgstr ""
+
+#: gui/gdmgreeter.c:195 gui/gdmlogin.c:272
+msgid "Welcome to "
+msgstr "Bienvenue sur "
+
+#: gui/gdmgreeter.c:199 gui/gdmlogin.c:276
+msgid "gdm_parse_enriched_string: Could not malloc temporary buffer!"
+msgstr ""
+
+#: gui/gdmgreeter.c:273
+msgid "Logo not found. No image will be displayed!"
+msgstr "Logo non trouvé. Aucune image ne sera affichée!"
+
+#: gui/gdmgreeter.c:299
+#, fuzzy, c-format
+msgid "gdm_greeter_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_config_parse: Pas de fichier de configuration: %s. Abandon."
+
+#: gui/gdmgreeter.c:323 gui/gdmlogin.c:403
+#, c-format
+msgid "messages/welcome=Welcome to %h"
+msgstr "messages/welcome=Bienvenue sur %h"
+
+#: gui/gdmgreeter.c:424 gui/gdmlogin.c:527 gui/gdmlogin.c:557
+#, c-format
+msgid ""
+"You have chosen %s for this session, but your default setting is %s.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+
+#: gui/gdmgreeter.c:432
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+
+#: gui/gdmgreeter.c:440
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"You will be logged in using the %s environment."
+msgstr ""
+
+#: gui/gdmgreeter.c:453
+#, c-format
+msgid ""
+"You have chosen the language %s for this session, but your default setting "
+"is %s.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+
+#: gui/gdmgreeter.c:461
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+
+#: gui/gdmgreeter.c:469
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Your environment will be %s."
+msgstr ""
+
+#: gui/gdmgreeter.c:500
+msgid "Invalid username or password!"
+msgstr "Mot de passe ou nom d'utilisateur invalide!"
+
+#: gui/gdmgreeter.c:526 gui/gdmlogin.c:354
+msgid "Are you sure you want to reboot the machine?"
+msgstr "Voulez-vous vraiment redémarrer?"
+
+#: gui/gdmgreeter.c:555 gui/gdmlogin.c:366
+msgid "Are you sure you want to halt the machine?"
+msgstr "Voulez-vous vraiment arréter le système?"
+
+#: gui/gdmgreeter.c:812
+#, fuzzy
+msgid "gdm_greeter_session_init: Session script directory not found!"
+msgstr "gdm_slave_session_init: Fin de la session!"
+
+#: gui/gdmgreeter.c:865 gui/gdmlogin.c:694
+msgid "No session scripts found. Aborting!"
+msgstr ""
+
+#: gui/gdmgreeter.c:869 gui/gdmlogin.c:698
+#, c-format
+msgid "No default session link found. Using %s.\n"
+msgstr ""
+
+#. Login button
+#: gui/gdmgreeter.c:1029
+msgid "Login"
+msgstr "Login"
+
+#. Init sessions menu
+#: gui/gdmgreeter.c:1041
+msgid "Sessions"
+msgstr "Sessions"
+
+#. Language selection support
+#: gui/gdmgreeter.c:1048
+msgid "Languages"
+msgstr ""
+
+#: gui/gdmgreeter.c:1058 gui/gdmlogin.c:960
+msgid "Reboot..."
+msgstr "Redémarrage..."
+
+#: gui/gdmgreeter.c:1064 gui/gdmlogin.c:966
+msgid "Halt..."
+msgstr "Arrêt..."
+
+#: gui/gdmgreeter.c:1071
+msgid "Suspend"
+msgstr ""
+
+#: gui/gdmgreeter.c:1078 gui/gdmlogin.c:972
+msgid "System"
+msgstr "Système"
+
+#: gui/gdmgreeter.c:1086 gui/gdmlogin.c:986
+#, c-format
+msgid "Can't open icon file: %s. Suspending iconify feature!"
+msgstr ""
+
+#: gui/gdmgreeter.c:1090 gui/gdmlogin.c:990
+msgid "Iconify"
+msgstr ""
+
+#. Option button
+#: gui/gdmgreeter.c:1099
+msgid "Options..."
+msgstr ""
+
+#: gui/gdmgreeter.c:1531
+#, c-format
+msgid "Can't open NofaceImageFile: %s. Suspending face browser!"
+msgstr ""
+
+#: gui/gdmgreeter.c:1686
+msgid "main: Error setting up USR1 signal handler"
+msgstr "main: Erreur lors de la configuration du gestionnaire du signal USR1"
+
+#: gui/gdmgreeter.c:1694
+#, fuzzy
+msgid "main: Error setting up USR2 signal handler"
+msgstr "main: Erreur lors de la configuration du gestionnaire du signal USR1"
+
+#: gui/gdmlogin.c:382
+#, fuzzy, c-format
+msgid "gdm_login_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_config_parse: Pas de fichier de configuration: %s. Abandon."
+
+#: gui/gdmlogin.c:508
+#, c-format
+msgid ""
+"Your preferred session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+
+#: gui/gdmlogin.c:616
+#, c-format
+msgid "%s session selected"
+msgstr ""
+
+#: gui/gdmlogin.c:632 gui/gdmlogin.c:723
+msgid "Last"
+msgstr ""
+
+#: gui/gdmlogin.c:647
+#, fuzzy
+msgid "gdm_login_session_init: Session script directory not found!"
+msgstr "gdm_slave_session_init: Fin de la session!"
+
+#: gui/gdmlogin.c:709
+#, c-format
+msgid "%s language selected"
+msgstr ""
+
+#: gui/gdmlogin.c:736
+msgid "A-M"
+msgstr ""
+
+#: gui/gdmlogin.c:742
+msgid "N-Z"
+msgstr ""
+
+#: gui/gdmlogin.c:748
+msgid "Other"
+msgstr ""
+
+#: gui/gdmlogin.c:946
+#, fuzzy
+msgid "Session"
+msgstr "Sessions"
+
+#: gui/gdmlogin.c:953
+msgid "Language"
+msgstr ""
+
+#: gui/gdmlogin.c:979
+msgid "Host chooser"
+msgstr ""
+
+#, fuzzy
+#~ msgid "gdm_server_usr1_handler: Could not open display %s"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_display_dispose: Closing display %s"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_local_servers_start: Starting %s"
+#~ msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#, fuzzy
+#~ msgid "gdm_display_manage: Forked slave: %d...\n"
+#~ msgstr "gdm_display_run: Echec du lancement d'un processus esclave pour %d"
+
+#, fuzzy
+#~ msgid "gdm_child_action: Server process returned unknown status %d"
+#~ msgstr "gdm_restart_slave: Le processus esclave a retourné un état inconnu!"
+
+#, fuzzy
+#~ msgid "gdm_child_action: Slave process returned unknown status %d"
+#~ msgstr "gdm_restart_slave: Le processus esclave a retourné un état inconnu!"
+
+#~ msgid "gdm_term_handler: Got TERM/INT. Going down!"
+#~ msgstr "gdm_term_handler: TERM/INT reçu. Arrêt!"
+
+#, fuzzy
+#~ msgid "gdm_auth_secure_display: Securing %s"
+#~ msgstr "gdm_auth_secure_display: Impossible d'effacer le fichier %s"
+
+#, fuzzy
+#~ msgid "gdm_slave_start: Starting slave process for %s"
+#~ msgstr "gdm_display_run: Echec du lancement d'un processus esclave pour %d"
+
+#, fuzzy
+#~ msgid "gdm_slave_start: Opening display %s"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_slave_greeter: Running greeter on %s"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_slave_greeter: Greeter on pid %d"
+#~ msgstr "gdm_slave_server_init: Xserver au pid %d"
+
+#, fuzzy
+#~ msgid "gdm_slave_greeter: Insufficient data from greeter in pipe"
+#~ msgstr "gdm_slave_server_init: Impossible de forker le processus Xserver!"
+
+#, fuzzy
+#~ msgid "gdm_slave_get_opts: Insufficient data from greeter in pipe"
+#~ msgstr "gdm_slave_server_init: Impossible de forker le processus Xserver!"
+
+#, fuzzy
+#~ msgid "gdm_slave_session_start: %s on %s"
+#~ msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#, fuzzy
+#~ msgid "gdm_slave_session_stop: %s on %s"
+#~ msgstr "gdm_slave_session_init: Attente de %d"
+
+#, fuzzy
+#~ msgid "gdm_slave_session_cleanup: %s on %s"
+#~ msgstr "gdm_slave_session_init: Attente de %d"
+
+#, fuzzy
+#~ msgid "gdm_slave_session_cleanup: Running post session script"
+#~ msgstr "gdm_slave_session_init: Fin de la session!"
+
+#, fuzzy
+#~ msgid "gdm_slave_session_cleanup: Killing windows"
+#~ msgstr "gdm_slave_session_init: Fin de la session!"
+
+#, fuzzy
+#~ msgid "gdm_slave_term_handler: %s got TERM signal"
+#~ msgstr "gdm_term_handler: TERM/INT reçu. Arrêt!"
+
+#, fuzzy
+#~ msgid "gdm_slave_child_handler: %d died"
+#~ msgstr "gdm_slave_display_init: gdmgreeter a retourné 'User'!"
+
+#, fuzzy
+#~ msgid "gdm_slave_child_handler: %d returned %d"
+#~ msgstr "gdm_slave_display_init: gdmgreeter a retourné 'User'!"
+
+#, fuzzy
+#~ msgid "gdm_slave_windows_kill: Could not open display %s"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_slave_windows_kill: Killing windows on %s"
+#~ msgstr "gdm_slave_server_init: Xserver au pid %d"
+
+#, fuzzy
+#~ msgid "gdm_slave_windows_kill: Killing child 0x%x"
+#~ msgstr "gdm_slave_server_init: Xserver au pid %d"
+
+#, fuzzy
+#~ msgid "gdm_slave_xioerror_handler: I/O error for display %s"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_slave_xsync_handler: Xping failed for display %s"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_slave_xsync_ping: Pinging %s"
+#~ msgstr "gdm_slave_session_init: Attente de %d"
+
+#, fuzzy
+#~ msgid "gdm_slave_xsync_ping: Pinging %s returned %d"
+#~ msgstr "gdm_slave_server_init: Xserver au pid %d"
+
+#, fuzzy
+#~ msgid "gdm_server_start: %s"
+#~ msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#, fuzzy
+#~ msgid "gdm_server_start: Old server found (%d). Killing."
+#~ msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#, fuzzy
+#~ msgid "gdm_server_start: '%s'"
+#~ msgstr "gdm_slave_session_init: Impossible de démarrer la session `%s'"
+
+#, fuzzy
+#~ msgid "gdm_server_restart: Server for %s restarting!"
+#~ msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#, fuzzy
+#~ msgid "gdm_server_usr1_handler: Starting display %s!"
+#~ msgstr "gdm_slave_server_init: Impossible d'ouvrir le display %s\n"
+
+#, fuzzy
+#~ msgid "gdm_server_usr1_handler: Sleeping %d on a retry"
+#~ msgstr "gdm_slave_server_init: Xserver au pid %d"
+
+#~ msgid "Unknown session '%s' using default!"
+#~ msgstr "Session '%s'inconnue; utilisation de la session par défaut!"
+
+#~ msgid "Not supported yet. Please restart gdm to reread config!"
+#~ msgstr "Pas encore supporté. Relancez gdm pour relire la configuration!"
+
+#~ msgid "gdm_restart_slave: Giving up on display %s"
+#~ msgstr "gdm_restart_slave: Abandon sur l'affichage %s"
+
+#~ msgid "gdm_main: Error setting up HUP signal handler"
+#~ msgstr ""
+#~ "gdm_main: Erreur lors de la configuration du gestionnaire du signal HUP"
+
+#~ msgid "No configuration file: %s. Aborting."
+#~ msgstr "Pas de fichier de configuration: %s. Abandon."
+
+#, fuzzy
+#~ msgid "gdm_slave_greet_init: Error setting up PIPE signal handler"
+#~ msgstr ""
+#~ "gdm_main: Erreur lors de la configuration du gestionnaire du signal INT"
+
+#, fuzzy
+#~ msgid "gdm_slave_greet_init: Error: %s"
+#~ msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#, fuzzy
+#~ msgid "gdm_slave_greet_init: login: %d, passwd: %d\n"
+#~ msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#, fuzzy
+#~ msgid "gdm_slave_greet_init: login: %s, passwd: %s\n"
+#~ msgstr "gdm_slave_server_init: Serveur X non trouvé: %s"
+
+#~ msgid "messages/session=Sessions"
+#~ msgstr "messages/session=Sessions"
+
+#~ msgid "messages/system=System"
+#~ msgstr "messages/system=Système"
+
+#~ msgid "messages/halt=Halt system..."
+#~ msgstr "messages/halt=Arréter le système..."
+
+#~ msgid "messages/reboot=Reboot system..."
+#~ msgstr "messages/reboot=Redémarrer le système..."
+
+#~ msgid "messages/iconify=Iconify login window"
+#~ msgstr "messages/iconify=Iconifier la fenêtre de login"
+
+#~ msgid "messages/loginbutton=Login"
+#~ msgstr "messages/loginbutton=Login"
+
+#~ msgid "messages/optionbutton=Optiones"
+#~ msgstr "messages/optionbutton=Options"
+
+#~ msgid "messages/loginentry=Login:"
+#~ msgstr "messages/loginentry=Utilisateur:"
+
+#~ msgid "messages/passwordentry=Password:"
+#~ msgstr "messages/passwordentry=Mot de passe:"
+
+#~ msgid "Error: %s"
+#~ msgstr "Erreur: %s"
+
+#~ msgid "User is: %s!"
+#~ msgstr "L'utilisateur est: %s!"
diff --git a/po/no.po b/po/no.po
new file mode 100644
index 00000000..59f9a3e9
--- /dev/null
+++ b/po/no.po
@@ -0,0 +1,949 @@
+# Norwegian translation of gdm (bokmål dialect).
+# Copyright (C) 1998,1999 Free Software Foundation, Inc.
+# Kjartan Maraas <kmaraas@fib.hl.no>, 1998,1999.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gdm 0.5\n"
+"POT-Creation-Date: 1999-04-08 02:02+0200\n"
+"PO-Revision-Date: 1999-02-16 00:30+0100\n"
+"Last-Translator: Kjartan Maraas <kmaraas@fib.hl.no>\n"
+"Language-Team: Norwegian <no@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8-bit\n"
+
+#: daemon/gdm.c:136
+#, c-format
+msgid "gdm_config_parse: No configuration file: %s. Aborting."
+msgstr "gdm_config_parse: Ingen konfigurasjonsfil: %s. Avbryter."
+
+#: daemon/gdm.c:177
+msgid "gdm_config_parse: No greeter specified and default not found."
+msgstr "gdm_config_parse: Ingen velkomst spesifisert og forvalg ikke funnet."
+
+#: daemon/gdm.c:189
+msgid "gdm_config_parse: No authdir specified and default not found."
+msgstr ""
+"gdm_config_parse: Ingen autentiseringskatalog spesifisert og forvalg ikke "
+"funnet."
+
+#: daemon/gdm.c:207
+msgid ""
+"gdm_config_parse: No sessions directory specified and default not found."
+msgstr ""
+"gdm_config_parse: Ingen sesjonskatalog spesifisert og forvalgt ikke funnet."
+
+#: daemon/gdm.c:219
+msgid "gdm_config_parse: Invalid server line in config file. Ignoring!"
+msgstr "gdm_config_parse: Ugyldig tjenerlinje i konfigurasjonsfil. Ignorerer!"
+
+#: daemon/gdm.c:225
+msgid ""
+"gdm_config_parse: Xdmcp disabled and no local servers defined. Aborting!"
+msgstr ""
+"gdm_config_parse: Xdmcp slått av og ingen lokale tjenere definert. Avbryter!"
+
+#: daemon/gdm.c:230
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm user (%s). Aborting!"
+msgstr "gdm_config_parse: Kan ikke finne gdm brukeren (%s). Avbryter!"
+
+#: daemon/gdm.c:235
+msgid "gdm_config_parse: The gdm user should not be root. Aborting!"
+msgstr "gdm_config_parse: Brukeren for gdm bør ikke være root. Avbryter!"
+
+#: daemon/gdm.c:240
+#, c-format
+msgid "gdm_config_parse: Can't find the gdm group (%s). Aborting!"
+msgstr "gdm_config_parse: Kan ikke finne gdm gruppen (%s). Avbryter."
+
+#: daemon/gdm.c:246
+msgid "gdm_config_parse: The gdm group should not be root. Aborting!"
+msgstr "gdm_config_parse: Gruppen for gdm bør ikke være root. Avbryter!"
+
+#: daemon/gdm.c:253
+#, c-format
+msgid "gdm_config_parse: Authdir %s does not exist. Aborting."
+msgstr ""
+"gdm_config_parse: Autentiseringskatalogen %s eksisterer ikke. Avbryter."
+
+#: daemon/gdm.c:256
+#, c-format
+msgid "gdm_config_parse: Authdir %s is not a directory. Aborting."
+msgstr ""
+"gdm_config_parse: Autentiseringskatalogen %s er ikke en katalog. Avbryter."
+
+#: daemon/gdm.c:259
+#, c-format
+msgid ""
+"gdm_config_parse: Authdir %s is not owned by user %s, group %s. Aborting."
+msgstr ""
+"gdm_config_parse: Autentiseringskatalogen %s er eies ikke av bruker %s, "
+"gruppe %s. Avbryter."
+
+#: daemon/gdm.c:262
+#, c-format
+msgid ""
+"gdm_config_parse: Authdir %s has wrong permissions. Should be 750. Aborting."
+msgstr ""
+"gdm_config_parse: Autentiseringskatalogen %s har ikke riktige "
+"tilgangsrettigheter. Skal være 750. Avbryter."
+
+#: daemon/gdm.c:318
+#, c-format
+msgid "gdm_display_manage: Failed forking gdm slave process for %d"
+msgstr "gdm_display_manage: Feil under starting av gdm slaveprosess for %d"
+
+#: daemon/gdm.c:397
+#, c-format
+msgid "gdm_child_action: Aborting display %s"
+msgstr "gdm_child_action: Avbryter skjerm %s"
+
+#: daemon/gdm.c:402
+msgid "gdm_child_action: Master rebooting..."
+msgstr "gdm_child_action: Mester starter på nytt..."
+
+#: daemon/gdm.c:408
+#, c-format
+msgid "gdm_child_action: Reboot failed: %s"
+msgstr "gdm_child_action: Omstart feilet: %s"
+
+#: daemon/gdm.c:412
+msgid "gdm_child_action: Master halting..."
+msgstr "gdm_child_action: Mester stopper..."
+
+#: daemon/gdm.c:418
+#, c-format
+msgid "gdm_child_action: Halt failed: %s"
+msgstr "gdm_child_action: Stopp feilet: %s"
+
+#: daemon/gdm.c:512
+msgid "gdm_daemonify: fork() failed!"
+msgstr "gdm_daemonify: fork() feilet!"
+
+#: daemon/gdm.c:515
+#, c-format
+msgid "gdm_daemonify: setsid() failed: %s!"
+msgstr "gdm_daemonify: setsid() feilet: %s!"
+
+#: daemon/gdm.c:540
+msgid "Only root wants to run gdm\n"
+msgstr "Bare root vil kjøre gdm\n"
+
+#: daemon/gdm.c:558
+msgid ""
+"gdm already running. Aborting!\n"
+"\n"
+msgstr ""
+"gdm kjører allerede. Avbryter!\n"
+"\n"
+
+#: daemon/gdm.c:563
+#, c-format
+msgid ""
+"According to %s, gdm was already running (%d),\n"
+"but seems to have been murdered mysteriously.\n"
+msgstr ""
+"I følge %s, kjørte gdm allerede (%d), \n"
+"men ser ut til å ha blitt myrdet på mysterisk vis.\n"
+
+#: daemon/gdm.c:584
+msgid "gdm_main: Error setting up TERM signal handler"
+msgstr "gdm_main: Feil under oppsett av TERM signalhåndtereren"
+
+#: daemon/gdm.c:587
+msgid "gdm_main: Error setting up INT signal handler"
+msgstr "gdm_main: Feil under oppsett av INT signalhåndtereren"
+
+#: daemon/gdm.c:595
+msgid "gdm_main: Error setting up CHLD signal handler"
+msgstr "gdm_main: Feil under oppsett av CHLD signalhåndtereren"
+
+#: daemon/auth.c:62
+#, c-format
+msgid "gdm_auth_secure_display: Could not unlink %s file: %s"
+msgstr "gdm_auth_secure_display: Kunne ikke kjøre unlink på %s fil: %s"
+
+#: daemon/auth.c:73
+#, c-format
+msgid ""
+"gdm_auth_secure_display: Error starting xauth process: %s. Running insecure!"
+msgstr ""
+"gdm_auth_secure_display: Feil under oppstart av xauth prosessen: %s. Kjører "
+"usikkert!"
+
+#: daemon/auth.c:77
+msgid "gdm_auth_secure_display: Error forking xauth process. Running insecure!"
+msgstr ""
+"gdm_auth_secure_display: Feil under splitting av xauth prosess. Kjører "
+"usikkert!"
+
+#: daemon/auth.c:109
+#, c-format
+msgid "gdm_auth_user_add: Error starting xauth process: %s"
+msgstr "gdm_auth_user_add: Feil under oppstart av xauth prosess: %s"
+
+#: daemon/auth.c:113
+msgid "gdm_auth_user_add: Error forking xauth process."
+msgstr "gdm_auth_user_add: Feil under splitting av xauth prosess."
+
+#: daemon/auth.c:143
+#, c-format
+msgid "gdm_auth_user_remove: Error starting xauth process: %s"
+msgstr "gdm_auth_user_remove: Feil under oppstart av xauth prosess: %s"
+
+#: daemon/auth.c:147
+msgid "gdm_auth_user_remove: Error forking xauth process."
+msgstr "gdm_auth_user_remove: Feil under splitting av xauth prosess."
+
+#: daemon/filecheck.c:50 daemon/filecheck.c:83
+#, c-format
+msgid "%s: %s is not owned by uid %d. Skipping."
+msgstr "%s: %s er ikke eiet av uid %d. Hopper over."
+
+#: daemon/filecheck.c:57
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 755. Skipping."
+msgstr "%s: %s er skrivbar av gruppe/andre. Skal være 755. Hopper over."
+
+#: daemon/filecheck.c:76
+#, c-format
+msgid "%s: %s is not a regular file. Skipping."
+msgstr "%s: %s er ikke en vanlig fil. Hopper over."
+
+#: daemon/filecheck.c:90
+#, fuzzy, c-format
+msgid "%s: %s is writable by group. Should be 644. Skipping."
+msgstr "%s: %s er skrivbar av gruppe/andre. Skal være 644. Hopper over."
+
+#: daemon/filecheck.c:97
+#, c-format
+msgid "%s: %s is writable by group/other. Should be 644. Skipping."
+msgstr "%s: %s er skrivbar av gruppe/andre. Skal være 644. Hopper over."
+
+#: daemon/filecheck.c:104
+#, c-format
+msgid "%s: %s is bigger than sysadmin specified maximum file size. Skipping."
+msgstr ""
+"%s: %s er større enn maksimum filstørrelse spesifisert av "
+"systemadministrator. Hopper over."
+
+#: daemon/misc.c:121
+#, c-format
+msgid "gdm_exec_script: Failed starting: %s"
+msgstr "gdm_exec_script: Feil under oppstart: %s"
+
+#: daemon/misc.c:125
+msgid "gdm_exec_script: Can't fork script process!"
+msgstr "gdm_exec_script: Kan ikke splitte skriptprosess!"
+
+#: daemon/misc.c:153
+#, c-format
+msgid "gdm_exec_command: Failed starting: %s"
+msgstr "gdm_exec_command: Feil under oppstart: %s"
+
+#: daemon/misc.c:157
+msgid "gdm_exec_command: Can't fork process!"
+msgstr "gdm_exec_command: Kan ikke splitte prosessen!"
+
+#: daemon/server.c:82 daemon/server.c:213
+#, fuzzy
+msgid "gdm_server_start: Error setting up USR1 signal handler"
+msgstr "main: Feil under oppsett av USR1 signalhåndtereren"
+
+#: daemon/server.c:99
+#, fuzzy, c-format
+msgid "gdm_server_start: Could not open logfile for display %s!"
+msgstr "gdm_xdmcp_handle_manage: Kunne ikke åpne loggfil for skjerm %s!"
+
+#: daemon/server.c:129
+msgid "gdm_server_start: Error setting USR1 to SIG_IGN"
+msgstr ""
+
+#: daemon/server.c:146
+#, fuzzy, c-format
+msgid "gdm_server_start: Xserver not found: %s"
+msgstr "gdm_local_servers_start: Starter %s"
+
+#: daemon/server.c:152
+#, fuzzy
+msgid "gdm_server_start: Can't fork Xserver process!"
+msgstr "gdm_exec_script: Kan ikke splitte skriptprosess!"
+
+#: daemon/server.c:178
+#, fuzzy, c-format
+msgid "gdm_server_stop: Could not unlink auth file: %s!"
+msgstr "gdm_auth_secure_display: Kunne ikke kjøre unlink på %s fil: %s"
+
+#: daemon/server.c:237
+#, fuzzy
+msgid "gdm_server_restart: Error setting up ALARM signal handler"
+msgstr "main: Feil under oppsett av USR1 signalhåndtereren"
+
+#: daemon/slave.c:112
+msgid "gdm_slave_init: Error setting up TERM/INT signal handler"
+msgstr "gdm_slave_init: Feil under oppsett av TERM/INT signalhåndtereren"
+
+#: daemon/slave.c:120
+msgid "gdm_slave_init: Error setting up CHLD signal handler"
+msgstr "gdm_slave_init: Feil under oppsett av CHLD signalhåndtereren"
+
+#: daemon/slave.c:171
+msgid "gdm_slave_greeter: Can't init pipe to gdmgreeter"
+msgstr "gdm_slave_greeter: Kan ikke åpne rør til gdmvelkomst"
+
+#: daemon/slave.c:196
+#, c-format
+msgid "gdm_slave_greeter: Couldn't set groupid to %d"
+msgstr "gdm_slave_greeter: Kunne ikke sette gruppe-id til %d"
+
+#: daemon/slave.c:199
+#, c-format
+msgid "gdm_slave_greeter: Couldn't set userid to %d"
+msgstr "gdm_slave_greeter: Kunne ikke sette bruker-id til %d"
+
+#: daemon/slave.c:209
+#, c-format
+msgid "gdm_slave_greeter: Error starting greeter on display %s"
+msgstr "gdm_slave_greeter: Feil under oppstart av velkomst på skjerm %s"
+
+#: daemon/slave.c:212
+msgid "gdm_slave_greeter: Can't fork gdmgreeter process"
+msgstr "gdm_slave_greeter: Kan ikke splitte gdmvelkomst prosess"
+
+#: daemon/slave.c:280
+#, c-format
+msgid "gdm_slave_session_init: User '%s' not found. Aborting."
+msgstr "gdm_slave_session_init: Bruker '%s' ikke funnet. Avbryter."
+
+#: daemon/slave.c:299
+msgid ""
+"gdm_slave_session_init: Execution of PreSession script returned > 0. "
+"Aborting."
+msgstr ""
+"gdm_slave_session_init: Kjøring av PreSession skript returnerte > 0. "
+"Avbryter."
+
+#: daemon/slave.c:304
+msgid "gdm_slave_session_init: Error forking user session"
+msgstr "gdm_slave_session_init: Feil under splitting av brukersesjon"
+
+#: daemon/slave.c:312
+#, c-format
+msgid "gdm_slave_session_init: Could not setgid %d. Aborting."
+msgstr "gdm_slave_session_init: Kunne ikke kjøre setgid på %d. Avbryter."
+
+#: daemon/slave.c:315
+#, c-format
+msgid "gdm_slave_session_init: initgroups() failed for %s. Aborting."
+msgstr "gdm_slave_session_init: initgroups() feilet for %s. Avbryter."
+
+#: daemon/slave.c:318
+#, c-format
+msgid "gdm_slave_session_init: Could not become %s. Aborting."
+msgstr "gdm_slave_session_init: Kunne ikke bli %s. Avbryter."
+
+#: daemon/slave.c:373
+#, c-format
+msgid "gdm_slave_session_init: Could not start session `%s'"
+msgstr "gdm_slave_session_init: Kunne ikke starte sesjon `%s'"
+
+#: daemon/slave.c:547
+#, c-format
+msgid "gdm_slave_windows_kill_ioerror_handler: Fatal X error - Restarting %s"
+msgstr ""
+"gdm_slave_windows_kill_ioerror_handler: Fatal X feil - Starter %s på nytt"
+
+#: daemon/slave.c:579
+msgid "gdm_slave_xsync_ping: Error setting up ALARM signal handler"
+msgstr "gdm_slave_xsync_ping: Feil under oppsett av ALARM signalhåndtereren"
+
+#: daemon/verify.c:122 daemon/verify.c:185 gui/gdmgreeter.c:1363
+msgid "Login:"
+msgstr "Innlogging:"
+
+#: daemon/verify.c:128
+msgid "Can't find /etc/pam.d/gdm!"
+msgstr "Kan ikke finne /etc/pam.d/gdm!"
+
+#: daemon/verify.c:132
+#, c-format
+msgid "Can't set PAM_TTY=%s"
+msgstr "Kan ikke sette PAM_TTY=%s"
+
+#: daemon/verify.c:137 daemon/verify.c:189
+#, c-format
+msgid "Couldn't authenticate %s"
+msgstr "Kunne ikke autentisere %s"
+
+#: daemon/verify.c:142
+#, c-format
+msgid "Couldn't set acct. mgmt for %s"
+msgstr "Kunne ikke sette kontohåndtering for %s"
+
+#: daemon/verify.c:147
+#, c-format
+msgid "Couldn't set credentials for %s"
+msgstr "Kunne ikke sette credentials for %s"
+
+#: daemon/verify.c:152
+#, c-format
+msgid "Couldn't open session for %s"
+msgstr "Kunne ikke åpne sesjon for %s"
+
+#: daemon/verify.c:192
+msgid "User unknown"
+msgstr ""
+
+#: daemon/verify.c:208 gui/gdmgreeter.c:1369
+msgid "Password:"
+msgstr "Passord:"
+
+#: daemon/verify.c:213
+msgid "Incorrect password"
+msgstr ""
+
+#: daemon/xdmcp.c:172
+#, c-format
+msgid "gdm_xdmcp_init: Could not get server hostname: %s!"
+msgstr "gdm_xdmcp_init: Fikk ikke tjenerens vertsnavn: %s!"
+
+#: daemon/xdmcp.c:183
+msgid "gdm_xdmcp_init: Could not create socket!"
+msgstr "gdm_xdmcp_init: Kunne ikke opprette socket!"
+
+#: daemon/xdmcp.c:190
+msgid "gdm_xdmcp_init: Could not bind to XDMCP socket!"
+msgstr "gdm_xdmcp_init: Kunne ikke binde til XDMCP socket!"
+
+#: daemon/xdmcp.c:225
+msgid "gdm_xdmcp_decode: Could not create XDMCP buffer!"
+msgstr "gdm_xdmcp_decode: Kunne ikke opprette XDMCP buffer!"
+
+#: daemon/xdmcp.c:230
+msgid "gdm_xdmcp_decode: Could not read XDMCP header!"
+msgstr "gdm_xdmcp_decode: Kunne ikke lese XDMCP header!"
+
+#: daemon/xdmcp.c:235
+msgid "gdm_xdmcp_decode: Incorrect XDMCP version!"
+msgstr "gdm_xdmcp_decode: Feil XDMCP versjon!"
+
+#: daemon/xdmcp.c:271
+#, c-format
+msgid "gdm_xdmcp_decode_packet: Unknown opcode from host %s"
+msgstr "gdm_xdmcp_decode_packet: Ukjent opkode fra vert %s"
+
+#: daemon/xdmcp.c:289
+msgid "gdm_xdmcp_query: Could not extract authlist from packet"
+msgstr "gdm_xdmcp_query: Kunne ikke hente ut autentiseringsliste fra pakke"
+
+#: daemon/xdmcp.c:300
+msgid "gdm_xdmcp_query: Error in checksum"
+msgstr "gdm_xdmcp_query: Feil i sjekksum"
+
+#: daemon/xdmcp.c:323
+msgid "GNOME"
+msgstr "GNOME"
+
+#: daemon/xdmcp.c:347
+#, c-format
+msgid "Denied XDMCP query from host %s"
+msgstr ""
+
+#: daemon/xdmcp.c:349
+msgid "Display not authorized to connect"
+msgstr "Skjerm ikke autorisert til å koble til"
+
+#: daemon/xdmcp.c:382
+#, c-format
+msgid "gdm_xdmcp_handle_request: Got REQUEST from banned host %s"
+msgstr "gdm_xdmcp_handle_request: Mottok REQUEST fra bannlyst vert %s"
+
+#: daemon/xdmcp.c:389
+msgid "gdm_xdmcp_handle_request: Could not read Display Number"
+msgstr "gdm_xdmcp_handle_request: Kunne ikke lese skjermnummer"
+
+#: daemon/xdmcp.c:395
+msgid "gdm_xdmcp_handle_request: Could not read Connection Type"
+msgstr "gdm_xdmcp_handle_request: Kunne ikke lese forbindelsestype"
+
+#: daemon/xdmcp.c:401
+msgid "gdm_xdmcp_handle_request: Could not read Client Address"
+msgstr "gdm_xdmcp_handle_request: Kunne ikke lese klientadresse"
+
+#: daemon/xdmcp.c:407
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Names"
+msgstr "gdm_xdmcp_handle_request: Kunne ikke lese autentiseringsnavn"
+
+#: daemon/xdmcp.c:413
+msgid "gdm_xdmcp_handle_request: Could not read Authentication Data"
+msgstr "gdm_xdmcp_handle_request: Kunne ikke lese autentiseringsdata"
+
+#: daemon/xdmcp.c:419
+msgid "gdm_xdmcp_handle_request: Could not read Authorization List"
+msgstr "gdm_xdmcp_handle_request: Kunne ikke lese autorisasjonslisten"
+
+#: daemon/xdmcp.c:430
+msgid "gdm_xdmcp_handle_request: Could not read Manufacturer ID"
+msgstr "gdm_xdmcp_handle_request: Kunne ikke lese produsent-ID"
+
+#: daemon/xdmcp.c:448
+#, c-format
+msgid "gdm_xdmcp_handle_request: Failed checksum from %s"
+msgstr "gdm_xdmcp_handle_request: Feilet sjekksum fra %s"
+
+#: daemon/xdmcp.c:566
+#, c-format
+msgid "gdm_xdmcp_handle_manage: Got Manage from banned host %s"
+msgstr "gdm_xdmcp_handle_manage: Mottok Manage fra bannlyst vert %s"
+
+#: daemon/xdmcp.c:573
+msgid "gdm_xdmcp_handle_manage: Could not read Session ID"
+msgstr "gdm_xdmcp_handle_manage: Kunne ikke lese sesjons-ID"
+
+#: daemon/xdmcp.c:579
+msgid "gdm_xdmcp_handle_manage: Could not read Display Number"
+msgstr "gdm_xdmcp_handle_manage: Kunne ikke lese skjermnummer"
+
+#: daemon/xdmcp.c:588
+msgid "gdm_xdmcp_manage: Could not read Display Class"
+msgstr "gdm_xdmcp_manage: Kunne ikke lese skjermklasse"
+
+#: daemon/xdmcp.c:607
+#, c-format
+msgid "gdm_xdmcp_handle_manage: Could not open logfile for display %s!"
+msgstr "gdm_xdmcp_handle_manage: Kunne ikke åpne loggfil for skjerm %s!"
+
+#: daemon/xdmcp.c:679
+#, c-format
+msgid "gdm_xdmcp_handle_keepalive: Got KEEPALIVE from banned host %s"
+msgstr "gdm_xdmcp_handle_keepalive: Mottok KEEPALIVE fra bannlyst vert %s"
+
+#: daemon/xdmcp.c:686
+msgid "gdm_xdmcp_handle_keepalive: Could not read Display Number"
+msgstr "gdm_xdmcp_handle_keepalive: Kunne ikke lese skjermnummer"
+
+#: daemon/xdmcp.c:692
+msgid "gdm_xdmcp_handle_keepalive: Could not read Session ID"
+msgstr "gdm_xdmcp_handle_keepalive: Kunne ikke lese sesjons-ID"
+
+#: gui/gdmchooser.c:336
+#, fuzzy, c-format
+msgid "gdm_chooser_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_greeter_parse_config: Ingen konfigurasjonsfil: %s. Avbryter."
+
+#: gui/gdmchooser.c:447
+#, fuzzy, c-format
+msgid "Can't open default host icon: %s"
+msgstr "Kunne ikke åpne sesjon for %s"
+
+#. Buttons
+#: gui/gdmchooser.c:512
+msgid "Connect"
+msgstr ""
+
+#: gui/gdmchooser.c:519
+msgid "Rescan"
+msgstr ""
+
+#: gui/gdmchooser.c:525
+msgid "Cancel"
+msgstr ""
+
+#: gui/gdmchooser.c:576 gui/gdmgreeter.c:1672 gui/gdmlogin.c:1102
+msgid "main: Error setting up HUP signal handler"
+msgstr "main: Feil under oppsett av HUP signalhåndtereren"
+
+#: gui/gdmchooser.c:579 gui/gdmgreeter.c:1675 gui/gdmlogin.c:1105
+msgid "main: Error setting up INT signal handler"
+msgstr "main: Feil under oppsett av INT signalhåndtereren"
+
+#: gui/gdmchooser.c:582 gui/gdmgreeter.c:1678 gui/gdmlogin.c:1108
+msgid "main: Error setting up TERM signal handler"
+msgstr "main: Feil under oppsett av TERM signalhåndtereren"
+
+#: gui/gdmgreeter.c:155
+msgid "Gnome Display Manager"
+msgstr "Gnome skjermhåndtering"
+
+#: gui/gdmgreeter.c:157
+msgid "Copyright Martin K. Petersen (C) 1998, 1999"
+msgstr "Copyright Martin K. Petersen (C) 1998, 1999"
+
+#: gui/gdmgreeter.c:159 gui/gdmlogin.c:328
+msgid ""
+"gdm manages local and remote displays and provides the user with a login "
+"window."
+msgstr ""
+"gdm håndterer lokale og eksterne skjermer og presenterer brukeren for et "
+"innloggingsvindu."
+
+#: gui/gdmgreeter.c:194 gui/gdmlogin.c:271
+msgid "gdm_parse_enriched_string: String too long!"
+msgstr "gdm_parse_enriched_string: Strengen er for lang!"
+
+#: gui/gdmgreeter.c:195 gui/gdmlogin.c:272
+msgid "Welcome to "
+msgstr "Velkommen til "
+
+#: gui/gdmgreeter.c:199 gui/gdmlogin.c:276
+msgid "gdm_parse_enriched_string: Could not malloc temporary buffer!"
+msgstr "gdm_parse_enriched_string: Klarte ikke å malloc midlertidig buffer! "
+
+#: gui/gdmgreeter.c:273
+msgid "Logo not found. No image will be displayed!"
+msgstr "Logo ikke funnet. Bilde vil ikke bli vist!"
+
+#: gui/gdmgreeter.c:299
+#, c-format
+msgid "gdm_greeter_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_greeter_parse_config: Ingen konfigurasjonsfil: %s. Avbryter."
+
+#: gui/gdmgreeter.c:323 gui/gdmlogin.c:403
+#, c-format
+msgid "messages/welcome=Welcome to %h"
+msgstr "beskjeder/velkomst=Velkommen til %h"
+
+#: gui/gdmgreeter.c:424 gui/gdmlogin.c:527 gui/gdmlogin.c:557
+#, c-format
+msgid ""
+"You have chosen %s for this session, but your default setting is %s.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Du har valgt %s for denne sesjonen, men forvalgt innstilling er %s.\n"
+"Ønsker du å gjøre %s til forvalg for fremtidige sesjoner?"
+
+#: gui/gdmgreeter.c:432
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Din forrige sesjonstype %s er ikke installert på denne maskinen.\n"
+"Ønsker du å gjøre %s til forvalg for fremtidige sesjoner?"
+
+#: gui/gdmgreeter.c:440
+#, c-format
+msgid ""
+"Your previous session type %s is not installed on this machine.\n"
+"You will be logged in using the %s environment."
+msgstr ""
+"Din forrige sesjonstype %s er ikke installert på denne maskinen.\n"
+"Du vil bli logget inn til %s miljøet."
+
+#: gui/gdmgreeter.c:453
+#, c-format
+msgid ""
+"You have chosen the language %s for this session, but your default setting "
+"is %s.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+"Du har valgt språket %s for denne sesjonen, men din forvalgte innstilling er "
+"%s.\n"
+"Ønsker du å gjøre %s til forvalgt språk for fremtidige sesjoner?"
+
+#: gui/gdmgreeter.c:461
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Do you wish to make %s the default language for future sessions?"
+msgstr ""
+"Ditt forrige språk %s er ikke installert på denne maskinen.\n"
+"Ønsker du å gjøre %s til forvalgt språk for fremtidige sesjoner?"
+
+#: gui/gdmgreeter.c:469
+#, c-format
+msgid ""
+"Your previous language %s is not installed on this machine.\n"
+"Your environment will be %s."
+msgstr ""
+"Ditt forrige språk %s er ikke installert på denne maskinen.\n"
+"Ditt miljø vil være %s."
+
+#: gui/gdmgreeter.c:500
+msgid "Invalid username or password!"
+msgstr "Ugyldig brukernavn eller passord!"
+
+#: gui/gdmgreeter.c:526 gui/gdmlogin.c:354
+msgid "Are you sure you want to reboot the machine?"
+msgstr "Er du sikker på at du vil starte maskinen på nytt?"
+
+#: gui/gdmgreeter.c:555 gui/gdmlogin.c:366
+msgid "Are you sure you want to halt the machine?"
+msgstr "Er du sikker på at du vil stoppe maskinen?"
+
+#: gui/gdmgreeter.c:812
+msgid "gdm_greeter_session_init: Session script directory not found!"
+msgstr "gdm_greeter_session_init: Sesjonens skriptkatalog ikke funnet!"
+
+#: gui/gdmgreeter.c:865 gui/gdmlogin.c:694
+msgid "No session scripts found. Aborting!"
+msgstr "Ingen sesjonsskript funnet. Avbryter!"
+
+#: gui/gdmgreeter.c:869 gui/gdmlogin.c:698
+#, c-format
+msgid "No default session link found. Using %s.\n"
+msgstr "Ingen forvalgt sesjonlenke funnet. Bruker %s.\n"
+
+#. Login button
+#: gui/gdmgreeter.c:1029
+msgid "Login"
+msgstr "Innlogging"
+
+#. Init sessions menu
+#: gui/gdmgreeter.c:1041
+msgid "Sessions"
+msgstr "Sesjoner"
+
+#. Language selection support
+#: gui/gdmgreeter.c:1048
+msgid "Languages"
+msgstr "Språk"
+
+#: gui/gdmgreeter.c:1058 gui/gdmlogin.c:960
+msgid "Reboot..."
+msgstr "Omstart..."
+
+#: gui/gdmgreeter.c:1064 gui/gdmlogin.c:966
+msgid "Halt..."
+msgstr "Stopp..."
+
+#: gui/gdmgreeter.c:1071
+msgid "Suspend"
+msgstr "Suspender"
+
+#: gui/gdmgreeter.c:1078 gui/gdmlogin.c:972
+msgid "System"
+msgstr "System"
+
+#: gui/gdmgreeter.c:1086 gui/gdmlogin.c:986
+#, c-format
+msgid "Can't open icon file: %s. Suspending iconify feature!"
+msgstr "Kan ikke åpne ikonfilen: %s. Suspenderer ikonofiseringsfunksjonen!"
+
+#: gui/gdmgreeter.c:1090 gui/gdmlogin.c:990
+msgid "Iconify"
+msgstr "Ikonifiser"
+
+#. Option button
+#: gui/gdmgreeter.c:1099
+msgid "Options..."
+msgstr "Alternativer..."
+
+#: gui/gdmgreeter.c:1531
+#, c-format
+msgid "Can't open NofaceImageFile: %s. Suspending face browser!"
+msgstr "Kan ikke åpne NofaceImageFile: %s. Suspenderer ansiktsvisning!"
+
+#: gui/gdmgreeter.c:1686
+msgid "main: Error setting up USR1 signal handler"
+msgstr "main: Feil under oppsett av USR1 signalhåndtereren"
+
+#: gui/gdmgreeter.c:1694
+msgid "main: Error setting up USR2 signal handler"
+msgstr "main: Feil under oppsett av USR2 signalhåndtereren"
+
+#: gui/gdmlogin.c:382
+#, fuzzy, c-format
+msgid "gdm_login_parse_config: No configuration file: %s. Aborting."
+msgstr "gdm_greeter_parse_config: Ingen konfigurasjonsfil: %s. Avbryter."
+
+#: gui/gdmlogin.c:508
+#, fuzzy, c-format
+msgid ""
+"Your preferred session type %s is not installed on this machine.\n"
+"Do you wish to make %s the default for future sessions?"
+msgstr ""
+"Din forrige sesjonstype %s er ikke installert på denne maskinen.\n"
+"Ønsker du å gjøre %s til forvalg for fremtidige sesjoner?"
+
+#: gui/gdmlogin.c:616
+#, c-format
+msgid "%s session selected"
+msgstr ""
+
+#: gui/gdmlogin.c:632 gui/gdmlogin.c:723
+msgid "Last"
+msgstr ""
+
+#: gui/gdmlogin.c:647
+#, fuzzy
+msgid "gdm_login_session_init: Session script directory not found!"
+msgstr "gdm_greeter_session_init: Sesjonens skriptkatalog ikke funnet!"
+
+#: gui/gdmlogin.c:709
+#, c-format
+msgid "%s language selected"
+msgstr ""
+
+#: gui/gdmlogin.c:736
+msgid "A-M"
+msgstr ""
+
+#: gui/gdmlogin.c:742
+msgid "N-Z"
+msgstr ""
+
+#: gui/gdmlogin.c:748
+msgid "Other"
+msgstr ""
+
+#: gui/gdmlogin.c:946
+#, fuzzy
+msgid "Session"
+msgstr "Sesjoner"
+
+#: gui/gdmlogin.c:953
+#, fuzzy
+msgid "Language"
+msgstr "Språk"
+
+#: gui/gdmlogin.c:979
+msgid "Host chooser"
+msgstr ""
+
+#, fuzzy
+#~ msgid "gdm_server_usr1_handler: Could not open display %s"
+#~ msgstr "gdm_slave_windows_kill: Kunne ikke åpne skjerm %s"
+
+#~ msgid "gdm_display_dispose: Closing display %s"
+#~ msgstr "gdm_display_dispose: Lukke skjerm %s"
+
+#~ msgid "gdm_display_dispose: Disposing %s"
+#~ msgstr "gdm_display_dispose: Fjerner %s"
+
+#~ msgid "gdm_display_manage: Managing %s"
+#~ msgstr "gdm_display_manage: Håndterer %s"
+
+#~ msgid "gdm_display_manage: Forked slave: %d...\n"
+#~ msgstr "gdm_display_manage: Splittet slave: %d...\n"
+
+#~ msgid "gdm_child_action: %s"
+#~ msgstr "gdm_child_action: %s"
+
+#~ msgid "gdm_child_action: Server process returned unknown status %d"
+#~ msgstr "gdm_child_action: Tjenerprosessen returnerte ukjent status %d"
+
+#~ msgid "gdm_child_action: Slave process returned unknown status %d"
+#~ msgstr "gdm_child_action: Slaveprosessen returnerte ukjent status %d"
+
+#~ msgid "gdm_child_handler: child %d returned %d"
+#~ msgstr "gdm_child_handler: barn %d returnerte %d"
+
+#~ msgid "gdm_display_unmanage: Stopping %s"
+#~ msgstr "gdm_display_unmanage: Stopper %s"
+
+#~ msgid "gdm_term_handler: Got TERM/INT. Going down!"
+#~ msgstr "gdm_term_handler: Fikk TERM/INT. Går ned!"
+
+#~ msgid "gdm_main: Here we go..."
+#~ msgstr "gdm_main: Så bærer det avsted..."
+
+#~ msgid "gdm_auth_secure_display: Securing %s"
+#~ msgstr "gdm_auth_secure_display: Sikrer %s"
+
+#~ msgid "gdm_auth_user_add: Adding cookie to %s"
+#~ msgstr "gdm_auth_user_add: Legger til cookie til %s"
+
+#~ msgid "gdm_auth_user_remove: Removing cookie from %s"
+#~ msgstr "gdm_auth_user_remove: Fjerner cookie fra %s"
+
+#~ msgid "gdm_slave_start: Starting slave process for %s"
+#~ msgstr "gdm_slave_start: Starter slaveprosess for %s"
+
+#~ msgid "gdm_slave_start: Opening display %s"
+#~ msgstr "gdm_slave_start: Åpner skjerm %s"
+
+#~ msgid "gdm_slave_greeter: Running greeter on %s"
+#~ msgstr "gdm_slave_greeter: Kjører velkomst på %s"
+
+#~ msgid "gdm_slave_greeter: Greeter on pid %d"
+#~ msgstr "gdm_slave_greeter: Velkomst på pid %d"
+
+#~ msgid "gdm_slave_greeter: No command followed STX"
+#~ msgstr "gdm_slave_greeter: Ingen kommando fulgte STX"
+
+#~ msgid "gdm_slave_greeter: Insufficient data from greeter in pipe"
+#~ msgstr "gdm_slave_greeter: Utilstrekkelig med data fra velkomst i røret"
+
+#~ msgid "gdm_slave_get_opts: Insufficient data from greeter in pipe"
+#~ msgstr "gdm_slave_get_opts: Utilstrekkelig med data fra velkomst i røret"
+
+#~ msgid "gdm_slave_session_start: %s on %s"
+#~ msgstr "gdm_slave_session_start: %s på %s"
+
+#~ msgid "gdm_slave_session_stop: %s on %s"
+#~ msgstr "gdm_slave_session_stop: %s på %s"
+
+#~ msgid "gdm_slave_session_cleanup: %s on %s"
+#~ msgstr "gdm_slave_session_cleanup: %s på %s"
+
+#~ msgid "gdm_slave_session_cleanup: Running post session script"
+#~ msgstr "gdm_slave_session_cleanup: Kjører avsluttende sesjonsskript"
+
+#~ msgid "gdm_slave_session_cleanup: Killing windows"
+#~ msgstr "gdm_slave_session_cleanup: Dreper vinduer"
+
+#~ msgid "gdm_slave_term_handler: %s got TERM signal"
+#~ msgstr "gdm_slave_term_handler: %s fikk TERM signalet"
+
+#~ msgid "gdm_slave_term_handler: Whacking greeter"
+#~ msgstr "gdm_slave_term_handler: Fjerner velkomst"
+
+#~ msgid "gdm_slave_term_handler: Whacking client connections"
+#~ msgstr "gdm_slave_term_handler: Fjerner klientforbindelser"
+
+#~ msgid "gdm_slave_child_handler: %d died"
+#~ msgstr "gdm_slave_child_handler: %d døde"
+
+#~ msgid "gdm_slave_child_handler: %d returned %d"
+#~ msgstr "gdm_slave_child_handler: %d returnerte %d"
+
+#~ msgid "gdm_slave_windows_kill: Killing windows on %s"
+#~ msgstr "gdm_slave_windows_kill: Dreper vinduer på %s"
+
+#~ msgid "gdm_slave_windows_kill: Killing child 0x%x"
+#~ msgstr "gdm_slave_windows_kill: Dreper barn 0x%x"
+
+#~ msgid "gdm_slave_windows_kill_error_handler: Blam"
+#~ msgstr "gdm_slave_windows_kill_error_handler: Pang"
+
+#~ msgid "gdm_slave_xioerror_handler: I/O error for display %s"
+#~ msgstr "gdm_slave_xioerror_handler: I/O feil for skjerm %s"
+
+#~ msgid "gdm_slave_xsync_handler: Xping failed for display %s"
+#~ msgstr "gdm_slave_xsync_handler: Xping feilet for skjerm %s"
+
+#~ msgid "gdm_slave_xsync_ping: Pinging %s"
+#~ msgstr "gdm_slave_xsync_ping: Pinger %s"
+
+#~ msgid "gdm_slave_xsync_ping: Pinging %s returned %d"
+#~ msgstr "gdm_slave_xsync_ping: Pinging av %s returnerte %d"
+
+#~ msgid "gdm_xdmcp_send_willing: Sending WILLING to %s"
+#~ msgstr "gdm_xdmcp_send_willing: Sender WILLING til %s"
+
+#~ msgid "gdm_xdmcp_send_unwilling: Sending UNWILLING to %s"
+#~ msgstr "gdm_xdmcp_send_unwilling: Sender UNWILLING til %s"
+
+#~ msgid "gdm_xdmcp_handle_request: Got REQUEST from %s"
+#~ msgstr "gdm_xdmcp_handle_request: Mottok REQUEST fra %s"
+
+#~ msgid "gdm_xdmcp_send_accept: Sending ACCEPT to %s with SessionID=%d"
+#~ msgstr "gdm_xdmcp_send_accept: Sender ACCEPT til %s med SejonsID=%d"
+
+#~ msgid "gdm_xdmcp_send_decline: Sending DECLINE to %s"
+#~ msgstr "gdm_xdmcp_send_decline: Sender DECLINE til %s"
+
+#~ msgid "gdm_xdmcp_manage: Got MANAGE from %s"
+#~ msgstr "gdm_xdmcp_manage: Mottok MANAGE fra %s"
+
+#~ msgid "gdm_xdmcp_manage: Got Display=%d, SessionID=%d from %s"
+#~ msgstr "gdm_xdmcp_manage: Mottok skjerm=%d, sesjons-ID=%d fra %s"
+
+#~ msgid "gdm_xdmcp_handle_manage: Sleeping %d on a retry"
+#~ msgstr "gdm_xdmcp_handle_manage: Sover %d ved gjentatt forsøk"
+
+#~ msgid "gdm_xdmcp_handle_keepalive: Got KEEPALIVE from %s"
+#~ msgstr "gdm_xdmcp_handle_keepalive: Mottok KEEPALIVE fra %s"