diff options
38 files changed, 5630 insertions, 0 deletions
@@ -0,0 +1 @@ +David Zeuthen <davidz@redhat.com> @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307 USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..4cd6c6a --- /dev/null +++ b/Makefile.am @@ -0,0 +1,16 @@ +## Process this file with automake to produce Makefile.in + +SUBDIRS = data policy src docs po + +NULL = + +EXTRA_DIST = \ + HACKING \ + mkinstalldirs \ + $(NULL) + +# xsltproc barfs on 'make distcheck'; disable for now +DISTCHECK_CONFIGURE_FLAGS=--disable-man-pages --disable-gtk-doc + +clean-local : + rm -f *~ @@ -0,0 +1 @@ +Write me @@ -0,0 +1 @@ +Write me diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..c910ef4 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,103 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +(test -f $srcdir/configure.ac) || { + echo -n "**Error**: Directory $srcdir does not look like the" + echo " top-level package directory" + exit 1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have autoconf installed." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && { + (libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have libtool installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + } +} + +(gtkdocize --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have gtk-doc installed to compile $PROJECT." + echo "Install the appropriate package for your distribution," + echo "or get the source tarball at http://ftp.gnome.org/pub/GNOME/sources/gtk-doc/" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have automake installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + NO_AUTOMAKE=yes +} + + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing aclocal. The version of automake" + echo "installed doesn't appear recent enough." + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run configure with no arguments." + echo "If you wish to pass any to it, please specify them on the" + echo $0 " command line." + echo +fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + + aclocalinclude="$ACLOCAL_FLAGS" + + if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then + if test -z "$NO_LIBTOOLIZE" ; then + echo "Running libtoolize..." + libtoolize --force --copy + fi + fi + echo "Running aclocal $aclocalinclude ..." + aclocal $aclocalinclude + if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then + echo "Running autoheader..." + autoheader + fi + echo "Running automake --gnu -Wno-portability $am_opt ..." + automake --add-missing --gnu -Wno-portability $am_opt + echo "Running autoconf ..." + autoconf + +intltoolize --copy --force --automake || exit 1 + +conf_flags="--enable-maintainer-mode --enable-gtk-doc" + +if test x$NOCONFIGURE = x; then + echo "Running $srcdir/configure $conf_flags $@ ..." + $srcdir/configure $conf_flags "$@" \ + && echo "Now type make to compile." || exit 1 +else + echo "Skipping configure process." +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..6925f7d --- /dev/null +++ b/configure.ac @@ -0,0 +1,208 @@ +dnl Process this file with autoconf to produce a configure script. + +AC_PREREQ(2.59c) +AC_INIT(xdg-hostname, 0.1, davidz@redhat.com) +AM_INIT_AUTOMAKE(xdg-hostname, 0.1) +AM_CONFIG_HEADER(config.h) +AM_MAINTAINER_MODE + +# libtool versioning - this applies to all libraries in this package +# +# See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details +# +LT_CURRENT=0 +LT_REVISION=0 +LT_AGE=0 +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +AC_SUBST(LT_AGE) + +AC_ISC_POSIX +AC_PROG_CC +AM_PROG_CC_STDC +AC_HEADER_STDC +AM_PROG_LIBTOOL +AC_PROG_MAKE_SET +AC_PROG_LN_S +AC_SYS_LARGEFILE +AM_PROG_CC_C_O + +# Taken from dbus +AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no) +AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode],enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE) +AC_ARG_ENABLE(man-pages, [ --enable-man-pages build manual pages],enable_man_pages=$enableval,enable_man_pages=yes) + +if test "${enable_man_page}" != no; then +dnl +dnl Check for xsltproc +dnl +AC_PATH_PROG([XSLTPROC], [xsltproc]) + if test -z "$XSLTPROC"; then + enable_man_pages=no + fi +fi +AM_CONDITIONAL(MAN_PAGES_ENABLED, test x$enable_man_pages = xyes) + +GTK_DOC_CHECK([1.3]) + +#### gcc warning flags + +if test "x$GCC" = "xyes"; then + changequote(,)dnl + case " $CFLAGS " in + *[\ \ ]-Wall[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wall" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wchar-subscripts[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wchar-subscripts" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wmissing-declarations[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wmissing-declarations" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wnested-externs[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wnested-externs" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wpointer-arith[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wpointer-arith" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wcast-align[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wcast-align" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wsign-compare[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wsign-compare" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wformat[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wformat" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-Wformat-security[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -Wformat-security" ;; + esac + + if test "x$enable_ansi" = "xyes"; then + case " $CFLAGS " in + *[\ \ ]-ansi[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -ansi" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-D_POSIX_C_SOURCE*) ;; + *) CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199309L" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-D_BSD_SOURCE[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -D_BSD_SOURCE" ;; + esac + + case " $CFLAGS " in + *[\ \ ]-pedantic[\ \ ]*) ;; + *) CFLAGS="$CFLAGS -pedantic" ;; + esac + fi + changequote([,])dnl +fi + +PKG_CHECK_MODULES(GLIB, [gio-2.0 >= 2.14.0]) +AC_SUBST(GIO_CFLAGS) +AC_SUBST(GIO_LIBS) + +PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.14.0 gio-2.0 >= 2.14.0]) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.0]) +AC_SUBST(DBUS_CFLAGS) +AC_SUBST(DBUS_LIBS) + +PKG_CHECK_MODULES(DBUS_GLIB, [dbus-glib-1 >= 0.73]) +AC_SUBST(DBUS_GLIB_CFLAGS) +AC_SUBST(DBUS_GLIB_LIBS) + +PKG_CHECK_MODULES(POLKIT, [polkit-dbus >= 0.9]) +AC_SUBST(POLKIT_CFLAGS) +AC_SUBST(POLKIT_LIBS) + +EXPAT_LIB="" +AC_ARG_WITH(expat, [ --with-expat=<dir> Use expat from here], + [ + expat=$withval + CPPFLAGS="$CPPFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" + ] + ) +AC_CHECK_HEADERS(expat.h, [AC_DEFINE(HAVE_EXPAT_H)], + [AC_MSG_ERROR([Can't find expat.h. Please install expat.])]) +AC_CHECK_LIB(expat,XML_ParserCreate,[EXPAT_LIBS="-lexpat"], + [AC_MSG_ERROR([Can't find expat library. Please install expat.])]) +AC_SUBST(EXPAT_LIBS) + +if test "x$GCC" = "xyes"; then + LDFLAGS="-Wl,--as-needed $LDFLAGS" +fi + +# ******************** +# Internationalisation +# ******************** + +IT_PROG_INTLTOOL([0.40.0]) +GETTEXT_PACKAGE=xdg-hostname +AC_SUBST([GETTEXT_PACKAGE]) +AM_GLIB_GNU_GETTEXT +AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[gettext domain]) + +AC_OUTPUT([ +Makefile +data/Makefile +policy/Makefile +src/Makefile +src/xdghostname/Makefile +src/daemon/Makefile +src/programs/Makefile +docs/version.xml +docs/Makefile +docs/man/Makefile +docs/dbus/Makefile +po/Makefile.in +]) + +dnl ========================================================================== +echo " + xdg-hostname $VERSION + ================ + + prefix: ${prefix} + libdir: ${libdir} + libexecdir: ${libexecdir} + bindir: ${bindir} + sbindir: ${sbindir} + datadir: ${datadir} + sysconfdir: ${sysconfdir} + localstatedir: ${localstatedir} + docdir: ${docdir} + + compiler: ${CC} + cflags: ${CFLAGS} + cppflags: ${CPPFLAGS} + xsltproc: ${XSLTPROC} + + Maintainer mode: ${USE_MAINTAINER_MODE} + Building verbose mode: ${enable_verbose_mode} + Building api docs: ${enable_gtk_doc} + Building man pages: ${enable_man_pages} +" diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..beec0cf --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,24 @@ +## Process this file with automake to produce Makefile.in + +servicedir = $(datadir)/dbus-1/system-services +service_in_files = org.freedesktop.Hostname1.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +dbusconfdir = $(sysconfdir)/dbus-1/system.d +dbusconf_in_files = org.freedesktop.Hostname1.conf.in +dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf) + +$(dbusconf_DATA): $(dbusconf_in_files) Makefile + cat $< > $@ + +# @sed -e "s|\@polkituser\@|$(POLKIT_USER)|" $< > $@ + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = org.freedesktop.Hostname1.xml $(service_in_files) $(dbusconf_in_files) + +clean-local : + rm -f *~ $(service_DATA) $(dbusconf_DATA) diff --git a/data/org.freedesktop.Hostname1.conf.in b/data/org.freedesktop.Hostname1.conf.in new file mode 100644 index 0000000..04ffb62 --- /dev/null +++ b/data/org.freedesktop.Hostname1.conf.in @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- --> + +<!DOCTYPE busconfig PUBLIC + "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> + <policy user="root"> + <allow own="org.freedesktop.Hostname1"/> + </policy> +</busconfig> diff --git a/data/org.freedesktop.Hostname1.service.in b/data/org.freedesktop.Hostname1.service.in new file mode 100644 index 0000000..48c8b59 --- /dev/null +++ b/data/org.freedesktop.Hostname1.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.freedesktop.Hostname +Exec=@libexecdir@/xdg-hostname-daemon-1 +User=root diff --git a/data/org.freedesktop.Hostname1.xml b/data/org.freedesktop.Hostname1.xml new file mode 100644 index 0000000..312ddde --- /dev/null +++ b/data/org.freedesktop.Hostname1.xml @@ -0,0 +1,627 @@ +<!DOCTYPE node PUBLIC +"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" [ + <!ENTITY ERROR_PERMISSION_DENIED "org.freedesktop.Hostname1.Error.PermissionDenied"> + <!ENTITY ERROR_INVALID_DATA "org.freedesktop.Hostname1.Error.InvalidData"> + <!ENTITY ERROR_FAILED "org.freedesktop.Hostname1.Error.Failed"> + <!ENTITY ERROR_HAS_TRANSIENT_DATA_PROVIDER "org.freedesktop.Hostname1.Error.HasTransientDataProvider"> +]> +<node name="/hostname1" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"> + + <interface name="org.freedesktop.Hostname1"> + <doc:doc> + <doc:description> + <doc:para> + This interface is usually implemented by the object + <doc:tt>/org/freedesktop/hostname1</doc:tt> + exported by a system D-Bus service with the well-known name + <doc:tt>org.freedesktop.Hostname1</doc:tt>. + </doc:para> + </doc:description> + </doc:doc> + + <!-- ******************************************************************************** --> + + <method name="SetDisplayHostname"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Sets the + <doc:ref type="property" to="Hostname1:configured-display-hostname">configured-display-hostname</doc:ref> + property. + Typically only user interface applications will call this method in response to an user initiated action. + </doc:para> + </doc:description> + <doc:permission> + The caller will need the following PolicyKit authorization: + <doc:list> + <doc:item> + <doc:term>org.freedesktop.hostname1.change</doc:term> + </doc:item> + </doc:list> + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller is not authorized</doc:error> + <doc:error name="&ERROR_INVALID_DATA;">if invalid data is passed</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="display_hostname" direction="in" type="s"> + <doc:doc> + <doc:summary> + The value for the display host name. + The passed in value is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:display-hostname">display-hostname</doc:ref> + property. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="SetHostname"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Sets the + <doc:ref type="property" to="Hostname1:configured-hostname">configured-hostname</doc:ref> + property. + Typically only user interface applications will call this method in response to an user initiated action. + </doc:para> + </doc:description> + <doc:permission> + The caller will need the following PolicyKit authorization: + <doc:list> + <doc:item> + <doc:term>org.freedesktop.hostname1.change</doc:term> + </doc:item> + </doc:list> + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller is not authorized</doc:error> + <doc:error name="&ERROR_INVALID_DATA;">if invalid data is passed</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="hostname" direction="in" type="s"> + <doc:doc> + <doc:summary> + The value for the host name. + The passed in value is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:hostname">hostname</doc:ref> + property. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="SetIconName"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Sets the + <doc:ref type="property" to="Hostname1:configured-icon-name">configured-icon-name</doc:ref> + property. + Typically only user interface applications will call this method in response to an user initiated action. + </doc:para> + </doc:description> + <doc:permission> + The caller will need the following PolicyKit authorization: + <doc:list> + <doc:item> + <doc:term>org.freedesktop.hostname1.change</doc:term> + </doc:item> + </doc:list> + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller is not authorized</doc:error> + <doc:error name="&ERROR_INVALID_DATA;">if invalid data is passed</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="icon_name" direction="in" type="s"> + <doc:doc> + <doc:summary> + The name for the host icon. + The passed in value is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:icon-name">icon-name</doc:ref> + property. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="SetUseTransientData"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Sets the + <doc:ref type="property" to="Hostname1:use-transient-data">use-transient-data</doc:ref> + property. + Typically only user interface applications will call this method in response to an user initiated action. + </doc:para> + </doc:description> + <doc:permission> + The caller will need the following PolicyKit authorization: + <doc:list> + <doc:item> + <doc:term>org.freedesktop.hostname1.change</doc:term> + </doc:item> + </doc:list> + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller is not authorized</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="use_transient_data" direction="in" type="b"> + <doc:doc> + <doc:summary> + Whether transient data should be used if available. See the + <doc:ref type="property" to="Hostname1:use-transient-data">use-transient</doc:ref> + property for details. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="RegisterTransientDataProvider"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Registers a provider for transient hostname data. A cookie + is returned that the provider can use for invoking methods like + <doc:ref type="method" to="Hostname1.SetTransientHostname">SetTransientHostname()</doc:ref> + to set transient data. The data is kept in memory and will be purged + when the provider calls + <doc:ref type="method" to="Hostname1.UnregisterTransientDataProvider">UnregisterTransientDataProvider()</doc:ref> + or disconnects from the system message bus. + Only a single client can provide transient hostname data at a time. + Typically only network configuration tools will need to + call this method. + </doc:para> + </doc:description> + <doc:permission> + Only the super user (<doc:tt>uid 0</doc:tt>) can invoke this method. + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_HAS_TRANSIENT_DATA_PROVIDER;">if another client has already registered for providing transient data</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="cookie" direction="out" type="s"> + <doc:doc> + <doc:summary> + A cookie to be used for providing transient data via methods such as + <doc:ref type="method" to="Hostname1.SetTransientHostname">SetTransientHostname()</doc:ref> + and to unregister as a transient data provider via the + <doc:ref type="method" to="Hostname1.UnregisterTransientDataProvider">UnregisterTransientDataProvider()</doc:ref> + method. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="UnregisterTransientDataProvider"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Unregisters a transient data provider previously registered with + <doc:ref type="method" to="Hostname1.RegisterTransientDataProvider">RegisterTransientDataProvider()</doc:ref>. + </doc:para> + </doc:description> + <doc:permission> + Only the super user (<doc:tt>uid 0</doc:tt>) can invoke this method. + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_INVALID_DATA;">if an invalid cookie is passed</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="cookie" direction="in" type="s"> + <doc:doc> + <doc:summary> + A cookie obtained from the + <doc:ref type="method" to="Hostname1.RegisterTransientDataProvider">RegisterTransientDataProvider()</doc:ref> + method. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="SetTransientDisplayHostname"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Sets the + <doc:ref type="property" to="Hostname1:transient-display-hostname">transient-display-hostname</doc:ref> + property. + Typically only network configuration tools will need to + call this method. + </doc:para> + </doc:description> + <doc:permission> + Only the super user (<doc:tt>uid 0</doc:tt>) can invoke this method. + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_INVALID_DATA;">if invalid data is passed</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="cookie" direction="in" type="s"> + <doc:doc> + <doc:summary> + A cookie obtained from the + <doc:ref type="method" to="Hostname1.RegisterTransientDataProvider">RegisterTransientDataProvider()</doc:ref> + method. + </doc:summary> + </doc:doc> + </arg> + + <arg name="display_hostname" direction="in" type="s"> + <doc:doc> + <doc:summary> + The value for the display host name. Any valid UTF-8 string can be used. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="SetTransientHostname"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Sets the + <doc:ref type="property" to="Hostname1:transient-hostname">transient-hostname</doc:ref> + property. + Typically only network configuration tools will need to + call this method. + </doc:para> + </doc:description> + <doc:permission> + Only the super user (<doc:tt>uid 0</doc:tt>) can invoke this method. + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_INVALID_DATA;">if invalid data is passed</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="cookie" direction="in" type="s"> + <doc:doc> + <doc:summary> + A cookie obtained from the + <doc:ref type="method" to="Hostname1.RegisterTransientDataProvider">RegisterTransientDataProvider()</doc:ref> + method. + </doc:summary> + </doc:doc> + </arg> + + <arg name="hostname" direction="in" type="s"> + <doc:doc> + <doc:summary> + The value for the host name. Can't be an empty string. Must conform to + limitations and constraints as described for the + <doc:ref type="property" to="Hostname1:hostname">hostname</doc:ref> + property. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <method name="SetTransientIconName"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <doc:doc> + <doc:description> + <doc:para> + Sets the + <doc:ref type="property" to="Hostname1:transient-icon-name">transient-icon-name</doc:ref> + property. + Typically only network configuration tools will need to + call this method. + </doc:para> + </doc:description> + <doc:permission> + Only the super user (<doc:tt>uid 0</doc:tt>) can invoke this method. + </doc:permission> + <doc:errors> + <doc:error name="&ERROR_INVALID_DATA;">if invalid data is passed</doc:error> + <doc:error name="&ERROR_FAILED;">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + + <arg name="cookie" direction="in" type="s"> + <doc:doc> + <doc:summary> + A cookie obtained from the + <doc:ref type="method" to="Hostname1.RegisterTransientDataProvider">RegisterTransientDataProvider()</doc:ref> + method. + </doc:summary> + </doc:doc> + </arg> + + <arg name="icon_name" direction="in" type="s"> + <doc:doc> + <doc:summary> + The name for the host icon. Must be an empty string to unset the icon, otherwise a themed + icon name conforming to + the freedesktop.org + <doc:ulink url="http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html">Icon Theme Specification</doc:ulink> + and + <doc:ulink url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">Icon Naming Specification</doc:ulink> + specifications. + </doc:summary> + </doc:doc> + </arg> + </method> + + <!-- ******************************************************************************** --> + + <signal name="Changed"> + <doc:doc> + <doc:description> + <doc:para> + Emitted when one or more properties change. + </doc:para> + </doc:description> + </doc:doc> + </signal> + + <!-- ******************************************************************************** --> + + <property name="display-hostname" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + The display hostname of the system. If empty, it means no display hostname + has been chosen for the system. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="hostname" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + The hostname of the system. Is never the empty string. Conforms to section 3.5 of + <doc:ulink url="http://www.ietf.org/rfc/rfc1034.txt">RFC 1034</doc:ulink> + with the hostname being a label: 7 bit ASCII without special characters, + whitespace or dots. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="icon-name" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + The name icon to use for the system. Is either an empty string if no icon is set, otherwise + a themed icon name conforming to + the freedesktop.org + <doc:ulink url="http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html">Icon Theme Specification</doc:ulink> + and + <doc:ulink url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">Icon Naming Specification</doc:ulink> + specifications. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="configured-display-hostname" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + The configured display hostname of the system. This is a user preference and can be changed with the + <doc:ref type="method" to="Hostname1.SetDisplayHostname">SetDisplayHostname()</doc:ref> + method. + This property is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:display-hostname">display-hostname</doc:ref> + property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="configured-hostname" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + The configured hostname of the system. This is a user preference and can be changed with the + <doc:ref type="method" to="Hostname1.SetHostname">SetHostname()</doc:ref> + method. + This property is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:hostname">hostname</doc:ref> + property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="configured-icon-name" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + The configured icon name of the system. This is a user preference and can be changed with the + <doc:ref type="method" to="Hostname1.SetIconName">SetIconName()</doc:ref> + method. + This property is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:icon-name">icon-name</doc:ref> + property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="use-transient-data" type="b" access="read"> + <doc:doc> + <doc:description> + <doc:para> + If <doc:tt>FALSE</doc:tt>, then transient data will be ignored when + computing the value of the + <doc:ref type="property" to="Hostname1:hostname">hostname</doc:ref>, + <doc:ref type="property" to="Hostname1:display-hostname">display-hostname</doc:ref> and + <doc:ref type="property" to="Hostname1:icon-name">icon-name</doc:ref> + properties. + This is a user preference and can be changed with the + <doc:ref type="method" to="Hostname1.SetIconName">SetUseTransientData()</doc:ref> + method. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="transient-display-hostname" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + If not blank, the display hostname currently provided by a registered transient data provider. + This property is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:display-hostname">display-hostname</doc:ref> + property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="transient-hostname" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + If not blank, the hostname currently provided by a registered transient data provider. + This property is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:hostname">hostname</doc:ref> + property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="transient-icon-name" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + If not blank, the icon name currently provided by a registered transient data provider. + This property is subject to the same format and limitations as the + <doc:ref type="property" to="Hostname1:icon-name">icon-name</doc:ref> + property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + <property name="can-set-hostname" type="b" access="read"> + <doc:doc> + <doc:description> + <doc:para> + Whether the + <doc:ref type="property" to="Hostname1:configured-hostname">configured-hostname</doc:ref> + property can be set using + <doc:ref type="method" to="Hostname1.SetHostname">SetHostname()</doc:ref>. + Note that even if this property has the value <doc:tt>TRUE</doc:tt>, authorization checks may + prevent any random client from changing the given property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <property name="can-set-display-hostname" type="b" access="read"> + <doc:doc> + <doc:description> + <doc:para> + Whether the + <doc:ref type="property" to="Hostname1:configured-display-hostname">configured-display-hostname</doc:ref> + property can be set using + <doc:ref type="method" to="Hostname1.SetDisplayHostname">SetDisplayHostname()</doc:ref>. + Note that even if this property has the value <doc:tt>TRUE</doc:tt>, authorization checks may + prevent any random client from changing the given property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <property name="can-set-icon-name" type="b" access="read"> + <doc:doc> + <doc:description> + <doc:para> + Whether the + <doc:ref type="property" to="Hostname1:configured-icon-name">configured-icon-name</doc:ref> + property can be set using + <doc:ref type="method" to="Hostname1.SetIconName">SetIconName()</doc:ref>. + Note that even if this property has the value <doc:tt>TRUE</doc:tt>, authorization checks may + prevent any random client from changing the given property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <property name="can-set-use-transient-data" type="b" access="read"> + <doc:doc> + <doc:description> + <doc:para> + Whether the + <doc:ref type="property" to="Hostname1:use-transient-data">use-transient-data</doc:ref> + property can be set using + <doc:ref type="method" to="Hostname1.SetUseTransientData">SetUseTransientData()</doc:ref>. + Note that even if this property has the value <doc:tt>TRUE</doc:tt>, authorization checks may + prevent any random client from changing the given property. + </doc:para> + </doc:description> + </doc:doc> + </property> + + <!-- ******************************************************************************** --> + + </interface> +</node> diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..43633ef --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,79 @@ + +SUBDIRS = man dbus + +NULL = + +AUTOMAKE_OPTIONS = 1.7 + +# The name of the module. +DOC_MODULE=xdg-hostname + +# The top-level SGML file. +DOC_MAIN_SGML_FILE=xdg-hostname-docs.xml + +# Extra options to supply to gtkdoc-scan +SCAN_OPTIONS=--ignore-headers=config.h + +# The directory containing the source code. Relative to $(srcdir) +DOC_SOURCE_DIR=../src/xdghostname + +# Used for dependencies +HFILE_GLOB=$(top_srcdir)/src/xdghostname/*.h +CFILE_GLOB=$(top_srcdir)/src/xdghostname/*.c + +# Headers to ignore +IGNORE_HFILES= \ + $(NULL) + +# CFLAGS and LDFLAGS for compiling scan program. Only needed +# if $(DOC_MODULE).types is non-empty. +INCLUDES = \ + $(DBUS_GLIB_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ + -I$(top_srcdir)/src/xdghostname \ + -I$(top_builddir)/src/xdghostname \ + $(NULL) + +GTKDOC_LIBS = \ + $(DBUS_GLIB_LIBS) \ + $(GLIB_LIBS) \ + $(GIO_LIBS) \ + $(top_builddir)/src/xdghostname/libxdg-hostname-gobject-1.la \ + $(NULL) + +# Extra options to supply to gtkdoc-mkdb +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +MKTMPL_OPTIONS= + +# Non-autogenerated SGML files to be included in $(DOC_MAIN_SGML_FILE) +content_files = \ + version.xml \ + dbus/org.freedesktop.Hostname1.ref.xml \ + man/xdg-hostname-1.xml \ + man/xdg-hostnamed-1.xml \ + $(NULL) + +# Images to copy into HTML directory +HTML_IMAGES = \ + $(NULL) + +# Extra options to supply to gtkdoc-fixref +FIXXREF_OPTIONS= + +MAINTAINERCLEANFILES = \ + *~ \ + Makefile.in \ + xdg-hostname.types \ + xdg-hostname-*.txt \ + $(NULL) + +if ENABLE_GTK_DOC +include $(top_srcdir)/gtk-doc.make +else +EXTRA_DIST = +endif + +EXTRA_DIST += version.xml.in diff --git a/docs/dbus/Makefile.am b/docs/dbus/Makefile.am new file mode 100644 index 0000000..e7bcfb7 --- /dev/null +++ b/docs/dbus/Makefile.am @@ -0,0 +1,11 @@ + +all : org.freedesktop.Hostname1.ref.xml + +org.freedesktop.Hostname1.ref.xml : $(top_srcdir)/data/org.freedesktop.Hostname1.xml $(top_srcdir)/docs/dbus/spec-to-docbook.xsl + echo "<?xml version=\"1.0\"?>""<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.1.2//EN\" \"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd\">" > $@ + $(XSLTPROC) --nonet $(top_srcdir)/docs/dbus/spec-to-docbook.xsl $< | tail -n +2 >> $@ + +EXTRA_DIST = spec-to-docbook.xsl dbus-introspect-docs.dtd + +clean-local : + rm -f *~ *.ref.xml diff --git a/docs/dbus/dbus-introspect-docs.dtd b/docs/dbus/dbus-introspect-docs.dtd new file mode 100644 index 0000000..ca918fb --- /dev/null +++ b/docs/dbus/dbus-introspect-docs.dtd @@ -0,0 +1,32 @@ +<!-- DTD for D-Bus Introspection Documentation --> + +<!ELEMENT doc (summary?,description?,errors?,permission?,since?,deprecated,seealso?)> + +<!ELEMENT summary (#PCDATA|ref)*> +<!ELEMENT description (#PCDATA|para|example)*> +<!ELEMENT errors (error)*> +<!ELEMENT permission (#PCDATA|ref|para)*> +<!ELEMENT since EMPTY> +<!ATTLIST since version CDATA #REQUIRED> +<!ELEMENT deprecated (#PCDATA|ref)> +<!ATTLIST deprecated version CDATA #REQUIRED> +<!ATTLIST deprecated instead CDATA #REQUIRED> +<!ELEMENT seealso (ref+)> + +<!ELEMENT error (#PCDATA|para)*> +<!ATTLIST error name CDATA #REQUIRED> +<!ELEMENT para (#PCDATA|example|code|list|ref)*> +<!ELEMENT example (#PCDATA|para|code|ref)*> +<!ATTLIST language (c|glib|python|shell) #REQUIRED> +<!ATTLIST title CDATA #IMPLIED> +<!ELEMENT list (item*)> +<!ATTLIST list type (bullet|number) #REQUIRED> +<!ELEMENT item (term|definition)*> +<!ELEMENT term (#PCDATA|ref)*> +<!ELEMENT definition (#PCDATA|para)*> + +<!ELEMENT code (#PCDATA)> +<!ATTLIST code lang CDATA #IMPLIED> +<!ELEMENT ref CDATA> +<!ATTLIST ref type (parameter|arg|signal|method|interface) #REQUIRED> +<!ATTLIST ref to CDATA #REQUIRED> diff --git a/docs/dbus/spec-to-docbook.xsl b/docs/dbus/spec-to-docbook.xsl new file mode 100644 index 0000000..1864414 --- /dev/null +++ b/docs/dbus/spec-to-docbook.xsl @@ -0,0 +1,543 @@ +<?xml version='1.0'?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd" + exclude-result-prefixes="doc"> +<!-- + Convert D-Bus Glib xml into DocBook refentries + Copyright (C) 2007 William Jon McCann + License: GPL +--> +<xsl:output method="xml" indent="yes" encoding="UTF-8"/> + +<xsl:template match="/"> + +<xsl:variable name="interface" select="//interface/@name"/> +<xsl:variable name="basename"> + <xsl:call-template name="interface-basename"> + <xsl:with-param name="str" select="$interface"/> + </xsl:call-template> +</xsl:variable> + +<refentry><xsl:attribute name="id"><xsl:value-of select="$basename"/></xsl:attribute> + <refmeta> + <refentrytitle role="top_of_page"><xsl:value-of select="//interface/@name"/></refentrytitle> + </refmeta> + + <refnamediv> + <refname><xsl:value-of select="//interface/@name"/></refname> + <refpurpose><xsl:value-of select="$basename"/> interface</refpurpose> + </refnamediv> + + <refsynopsisdiv role="synopsis"> + <title role="synopsis.title">Methods</title> + <synopsis> + <xsl:call-template name="methods-synopsis"> + <xsl:with-param name="basename" select="$basename"/> + </xsl:call-template> + </synopsis> + </refsynopsisdiv> + + <xsl:choose> + <xsl:when test="count(///signal) > 0"> + <refsect1 role="signal_proto"> + <title role="signal_proto.title">Signals</title> + <synopsis> + <xsl:call-template name="signals-synopsis"> + <xsl:with-param name="basename" select="$basename"/> + </xsl:call-template> + </synopsis> + </refsect1> + </xsl:when> + </xsl:choose> + + <refsect1 role="impl_interfaces"> + <title role="impl_interfaces.title">Implemented Interfaces</title> + <para> + Objects implementing <xsl:value-of select="$interface"/> also implements + org.freedesktop.DBus.Introspectable, + org.freedesktop.DBus.Properties + </para> + </refsect1> + + <xsl:choose> + <xsl:when test="count(///property) > 0"> + <refsect1 role="properties"> + <title role="properties.title">Properties</title> + <synopsis> + <xsl:call-template name="properties-synopsis"> + <xsl:with-param name="basename" select="$basename"/> + </xsl:call-template> + </synopsis> + </refsect1> + </xsl:when> + </xsl:choose> + + <refsect1 role="desc"> + <title role="desc.title">Description</title> + <para> + <xsl:apply-templates select="//interface/doc:doc"/> + </para> + </refsect1> + + <refsect1 role="details"> + <title role="details.title">Details</title> + <xsl:call-template name="method-details"> + <xsl:with-param name="basename" select="$basename"/> + </xsl:call-template> + </refsect1> + + <xsl:choose> + <xsl:when test="count(///signal) > 0"> + <refsect1 role="signals"> + <title role="signals.title">Signal Details</title> + <xsl:call-template name="signal-details"> + <xsl:with-param name="basename" select="$basename"/> + </xsl:call-template> + </refsect1> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="count(///property) > 0"> + <refsect1 role="property_details"> + <title role="property_details.title">Property Details</title> + <xsl:call-template name="property-details"> + <xsl:with-param name="basename" select="$basename"/> + </xsl:call-template> + </refsect1> + </xsl:when> + </xsl:choose> + +</refentry> +</xsl:template> + + +<xsl:template name="property-doc"> + <xsl:apply-templates select="doc:doc/doc:description"/> + + <variablelist role="params"> + <xsl:for-each select="arg"> +<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term> +<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem> +</varlistentry> + </xsl:for-each> + </variablelist> + + <xsl:apply-templates select="doc:doc/doc:since"/> + <xsl:apply-templates select="doc:doc/doc:deprecated"/> + <xsl:apply-templates select="doc:doc/doc:permission"/> + <xsl:apply-templates select="doc:doc/doc:seealso"/> +</xsl:template> + + +<xsl:template name="property-details"> + <xsl:param name="basename"/> + <xsl:variable name="longest"> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="@name"/> + </xsl:call-template> + </xsl:variable> + <xsl:for-each select="///property"> + <refsect2> + <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute></anchor>The "<xsl:value-of select="@name"/>" property</title> +<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm> +<programlisting>'<xsl:value-of select="@name"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="2"/></xsl:call-template> +<xsl:call-template name="property-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/></xsl:call-template></programlisting> + </refsect2> + + <xsl:call-template name="property-doc"/> + + </xsl:for-each> +</xsl:template> + +<xsl:template name="signal-doc"> + <xsl:apply-templates select="doc:doc/doc:description"/> + + <variablelist role="params"> + <xsl:for-each select="arg"> +<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term> +<listitem><simpara><xsl:value-of select="doc:doc/doc:summary"/></simpara></listitem> +</varlistentry> + </xsl:for-each> + </variablelist> + + <xsl:apply-templates select="doc:doc/doc:since"/> + <xsl:apply-templates select="doc:doc/doc:deprecated"/> + <xsl:apply-templates select="doc:doc/doc:permission"/> + <xsl:apply-templates select="doc:doc/doc:seealso"/> +</xsl:template> + +<xsl:template name="signal-details"> + <xsl:param name="basename"/> + <xsl:variable name="longest"> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="@name"/> + </xsl:call-template> + </xsl:variable> + <xsl:for-each select="///signal"> + <refsect2> + <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute></anchor>The <xsl:value-of select="@name"/> signal</title> +<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm> +<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting> + </refsect2> + + <xsl:call-template name="signal-doc"/> + + </xsl:for-each> +</xsl:template> + +<xsl:template match="doc:code"> +<programlisting> +<xsl:apply-templates /> +</programlisting> +</xsl:template> + +<xsl:template match="doc:tt"> + <literal> + <xsl:apply-templates /> + </literal> +</xsl:template> + +<xsl:template match="doc:i"> + <emphasis> + <xsl:apply-templates /> + </emphasis> +</xsl:template> + +<xsl:template match="doc:b"> + <emphasis role="bold"> + <xsl:apply-templates /> + </emphasis> +</xsl:template> + +<xsl:template match="doc:ulink"> + <ulink> + <xsl:attribute name="url"><xsl:value-of select="@url"/></xsl:attribute> + <xsl:value-of select="."/> + </ulink> +</xsl:template> + +<xsl:template match="doc:summary"> + <xsl:apply-templates /> +</xsl:template> + +<xsl:template match="doc:example"> +<informalexample> +<xsl:apply-templates /> +</informalexample> +</xsl:template> + +<xsl:template name="listitems-do-term"> + <xsl:param name="str"/> + <xsl:choose> + <xsl:when test="string-length($str) > 0"> + <emphasis role="bold"><xsl:value-of select="$str"/>: </emphasis> + </xsl:when> + </xsl:choose> +</xsl:template> + +<xsl:template name="do-listitems"> + <xsl:for-each select="doc:item"> + <listitem> + <xsl:call-template name="listitems-do-term"><xsl:with-param name="str" select="doc:term"/></xsl:call-template> + <xsl:apply-templates select="doc:definition"/> + </listitem> + </xsl:for-each> +</xsl:template> + +<xsl:template match="doc:list"> + <para> + <xsl:choose> + <xsl:when test="contains(@type,'number')"> + <orderedlist> + <xsl:call-template name="do-listitems"/> + </orderedlist> + </xsl:when> + <xsl:otherwise> + <itemizedlist> + <xsl:call-template name="do-listitems"/> + </itemizedlist> + </xsl:otherwise> + </xsl:choose> + </para> +</xsl:template> + +<xsl:template match="doc:para"> +<para> +<xsl:apply-templates /> +</para> +</xsl:template> + +<xsl:template match="doc:description"> +<xsl:apply-templates /> +</xsl:template> + +<xsl:template match="doc:since"> +<para role="since">Since <xsl:value-of select="@version"/> +</para> +</xsl:template> + +<xsl:template match="doc:deprecated"> + <xsl:variable name="name" select="../../@name"/> + <xsl:variable name="parent"> + <xsl:call-template name="interface-basename"> + <xsl:with-param name="str" select="../../../@name"/>/> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="type" select="name(../..)"/> + + <para role="deprecated"> + <warning><para><literal><xsl:value-of select="$name"/></literal> is deprecated since version <xsl:value-of select="@version"/> and should not be used in newly-written code. Use + + <xsl:variable name="to"> + <xsl:choose> + <xsl:when test="contains($type,'property')"> + <xsl:value-of select="$parent"/>:<xsl:value-of select="@instead"/> + </xsl:when> + <xsl:when test="contains($type,'signal')"> + <xsl:value-of select="$parent"/>::<xsl:value-of select="@instead"/> + </xsl:when> + <xsl:when test="contains($type,'method')"> + <xsl:value-of select="$parent"/>.<xsl:value-of select="@instead"/> + </xsl:when> + <xsl:when test="contains($type,'interface')"> + <xsl:value-of select="@instead"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@instead"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:call-template name="create-link"> + <xsl:with-param name="type" select="$type"/> + <xsl:with-param name="to" select="$to"/> + <xsl:with-param name="val" select="@instead"/> + </xsl:call-template> +instead.</para></warning> +</para> +</xsl:template> + +<xsl:template match="doc:permission"> +<para role="permission"> +<xsl:apply-templates /> +</para> +</xsl:template> + +<xsl:template match="doc:errors"> +<para role="errors"> +<xsl:apply-templates /> +</para> +</xsl:template> + +<xsl:template match="doc:seealso"> +<para> +See also: +<xsl:apply-templates /> + +</para> +</xsl:template> + +<xsl:template name="create-link"> + <xsl:param name="type"/> + <xsl:param name="to"/> + <xsl:param name="val"/> + + <xsl:choose> + <xsl:when test="contains($type,'property')"> + <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link> + </xsl:when> + <xsl:when test="contains($type,'signal')"> + <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><literal><xsl:value-of select="$val"/></literal></link> + </xsl:when> + <xsl:when test="contains($type,'method')"> + <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><function><xsl:value-of select="$val"/></function></link> + </xsl:when> + <xsl:when test="contains($type,'interface')"> + <link><xsl:attribute name="linkend"><xsl:value-of select="$to"/></xsl:attribute><xsl:value-of select="$val"/></link> + </xsl:when> + </xsl:choose> +</xsl:template> + +<xsl:template match="doc:ref"> + <xsl:call-template name="create-link"> + <xsl:with-param name="type" select="@type"/> + <xsl:with-param name="to" select="@to"/> + <xsl:with-param name="val" select="."/> + </xsl:call-template> +</xsl:template> + +<xsl:template name="method-doc"> + <xsl:apply-templates select="doc:doc/doc:description"/> + + <variablelist role="params"> + <xsl:for-each select="arg"> +<varlistentry><term><parameter><xsl:value-of select="@name"/></parameter>:</term> +<listitem><simpara><xsl:apply-templates select="doc:doc/doc:summary"/></simpara></listitem> +</varlistentry> + </xsl:for-each> + </variablelist> + + <xsl:apply-templates select="doc:doc/doc:since"/> + <xsl:apply-templates select="doc:doc/doc:deprecated"/> + + <xsl:choose> + <xsl:when test="count(doc:doc/doc:errors) > 0"> + <refsect3> + <title>Errors</title> + <variablelist role="errors"> + <xsl:for-each select="doc:doc/doc:errors/doc:error"> + <varlistentry> + <term><parameter><xsl:value-of select="@name"/></parameter>:</term> + <listitem><simpara><xsl:apply-templates select="."/></simpara></listitem> + </varlistentry> + </xsl:for-each> + </variablelist> + </refsect3> + </xsl:when> + </xsl:choose> + + <xsl:choose> + <xsl:when test="count(doc:doc/doc:permission) > 0"> + <refsect3> + <title>Permissions</title> + <xsl:apply-templates select="doc:doc/doc:permission"/> + </refsect3> + </xsl:when> + </xsl:choose> + + <xsl:apply-templates select="doc:doc/doc:seealso"/> +</xsl:template> + +<xsl:template name="method-details"> + <xsl:param name="basename"/> + <xsl:variable name="longest"> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="@name"/> + </xsl:call-template> + </xsl:variable> + <xsl:for-each select="///method"> + <refsect2> + <title><anchor role="function"><xsl:attribute name="id"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute></anchor><xsl:value-of select="@name"/> ()</title> +<indexterm><primary><xsl:value-of select="@name"/></primary><secondary><xsl:value-of select="$basename"/></secondary></indexterm> +<programlisting><xsl:value-of select="@name"/> (<xsl:call-template name="method-args"><xsl:with-param name="indent" select="string-length(@name) + 2"/><xsl:with-param name="prefix" select="."/></xsl:call-template>)</programlisting> + </refsect2> + + <xsl:call-template name="method-doc"/> + + </xsl:for-each> +</xsl:template> + + +<xsl:template name="properties-synopsis"> + <xsl:param name="basename"/> + <xsl:variable name="longest"> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="///property/@name"/> + </xsl:call-template> + </xsl:variable> + <xsl:for-each select="///property"> +<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>:<xsl:value-of select="@name"/></xsl:attribute>'<xsl:value-of select="@name"/>'</link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template> <xsl:call-template name="property-args"><xsl:with-param name="indent" select="$longest + 2"/></xsl:call-template> +</xsl:for-each> +</xsl:template> + + +<xsl:template name="signals-synopsis"> + <xsl:param name="basename"/> + <xsl:variable name="longest"> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="///signal/@name"/> + </xsl:call-template> + </xsl:variable> + <xsl:for-each select="///signal"> +<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>::<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="signal-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="///signal"/></xsl:call-template>) +</xsl:for-each> +</xsl:template> + + +<xsl:template name="methods-synopsis"> + <xsl:param name="basename"/> + <xsl:variable name="longest"> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="///method/@name"/> + </xsl:call-template> + </xsl:variable> + <xsl:for-each select="///method"> +<link><xsl:attribute name="linkend"><xsl:value-of select="$basename"/>.<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name"/></link><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@name) + 1"/></xsl:call-template>(<xsl:call-template name="method-args"><xsl:with-param name="indent" select="$longest + 2"/><xsl:with-param name="prefix" select="///method"/></xsl:call-template>) +</xsl:for-each> +</xsl:template> + + +<xsl:template name="method-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg"><xsl:value-of select="@direction"/> +<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="4 - string-length(@direction)"/></xsl:call-template>'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template> +<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">, +<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if> +</xsl:for-each> +</xsl:template> + + +<xsl:template name="signal-args"><xsl:param name="indent"/><xsl:param name="prefix"/><xsl:variable name="longest"><xsl:call-template name="find-longest"><xsl:with-param name="set" select="$prefix/arg/@type"/></xsl:call-template></xsl:variable><xsl:for-each select="arg">'<xsl:value-of select="@type"/>'<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$longest - string-length(@type) + 1"/></xsl:call-template> +<xsl:value-of select="@name"/><xsl:if test="not(position() = last())">, +<xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="$indent"/></xsl:call-template></xsl:if> +</xsl:for-each> +</xsl:template> + + +<xsl:template name="property-args"><xsl:param name="indent"/> +<xsl:value-of select="@access"/><xsl:call-template name="pad-spaces"><xsl:with-param name="width" select="9 - string-length(@access) + 1"/></xsl:call-template>'<xsl:value-of select="@type"/>' +</xsl:template> + + +<xsl:template name="pad-spaces"> + <xsl:param name="width"/> + <xsl:variable name="spaces" xml:space="preserve"> </xsl:variable> + <xsl:value-of select="substring($spaces,1,$width)"/> +</xsl:template> + + +<xsl:template name="find-longest"> + <xsl:param name="set"/> + <xsl:param name="index" select="1"/> + <xsl:param name="longest" select="0"/> + + <xsl:choose> + <xsl:when test="$index > count($set)"> + <!--finished looking--> + <xsl:value-of select="$longest"/> + </xsl:when> + <xsl:when test="string-length($set[$index])>$longest"> + <!--found new longest--> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="$set"/> + <xsl:with-param name="index" select="$index + 1"/> + <xsl:with-param name="longest" select="string-length($set[$index])"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!--this isn't any longer--> + <xsl:call-template name="find-longest"> + <xsl:with-param name="set" select="$set"/> + <xsl:with-param name="index" select="$index + 1"/> + <xsl:with-param name="longest" select="$longest"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> +</xsl:template> + + +<xsl:template name="interface-basename"> + <xsl:param name="str"/> + <xsl:choose> + <xsl:when test="contains($str,'.')"> + <xsl:call-template name="interface-basename"> + <xsl:with-param name="str" select="substring-after($str,'.')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$str"/> + </xsl:otherwise> + </xsl:choose> +</xsl:template> + +</xsl:stylesheet> diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am new file mode 100644 index 0000000..c5321bf --- /dev/null +++ b/docs/man/Makefile.am @@ -0,0 +1,20 @@ + +NULL = + +if MAN_PAGES_ENABLED + +man_MANS = xdg-hostname-1.1 \ + xdg-hostnamed-1.8 \ + $(NULL) + +%.1 %.8 : %.xml + $(XSLTPROC) -nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + +endif # MAN_PAGES_ENABLED + +EXTRA_DIST= xdg-hostname-1.xml \ + xdg-hostnamed-1.xml \ + $(NULL) + +clean-local: + rm -f *~ *.1 *.8 diff --git a/docs/man/xdg-hostname-1.xml b/docs/man/xdg-hostname-1.xml new file mode 100644 index 0000000..a916d71 --- /dev/null +++ b/docs/man/xdg-hostname-1.xml @@ -0,0 +1,44 @@ +<refentry id="xdg-hostname-1.1"> + <refentryinfo> + <title>xdg-hostname-1</title> + <date>October 2008</date> + <productname>xdg-hostname</productname> + </refentryinfo> + + <refmeta> + <refentrytitle>xdg-hostname-1</refentrytitle> + <manvolnum>1</manvolnum> + <refmiscinfo class="version"></refmiscinfo> + </refmeta> + + <refnamediv> + <refname>xdg-hostname-1</refname> + <refpurpose>Access and configure hostname data</refpurpose> + </refnamediv> + + <refsect1><title>DESCRIPTION</title> + <para> + Write me. + </para> + </refsect1> + + + <refsect1><title>AUTHOR</title> + <para> + Written by David Zeuthen <email>davidz@redhat.com</email> with + a lot of help from many others. + </para> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>hostname</refentrytitle><manvolnum>1</manvolnum> + </citerefentry>, + <citerefentry> + <refentrytitle>xdg-hostnamed-1</refentrytitle><manvolnum>8</manvolnum> + </citerefentry> + </para> + </refsect1> +</refentry> diff --git a/docs/man/xdg-hostnamed-1.xml b/docs/man/xdg-hostnamed-1.xml new file mode 100644 index 0000000..f53fa43 --- /dev/null +++ b/docs/man/xdg-hostnamed-1.xml @@ -0,0 +1,41 @@ +<refentry id="xdg-hostnamed-1.8"> + <refentryinfo> + <title>xdg-hostnamed-1</title> + <date>October 2008</date> + <productname>xdg-hostname</productname> + </refentryinfo> + + <refmeta> + <refentrytitle>xdg-hostnamed-1</refentrytitle> + <manvolnum>8</manvolnum> + <refmiscinfo class="version"></refmiscinfo> + </refmeta> + + <refnamediv> + <refname>xdg-hostnamed-1</refname> + <refpurpose>xdg-hostname daemon</refpurpose> + </refnamediv> + + <refsect1><title>DESCRIPTION</title> + <para> + Write me. + </para> + </refsect1> + + + <refsect1><title>AUTHOR</title> + <para> + Written by David Zeuthen <email>davidz@redhat.com</email> with + a lot of help from many others. + </para> + </refsect1> + + <refsect1> + <title>SEE ALSO</title> + <para> + <citerefentry> + <refentrytitle>xdg-hostname-1</refentrytitle><manvolnum>1</manvolnum> + </citerefentry> + </para> + </refsect1> +</refentry> diff --git a/docs/version.xml.in b/docs/version.xml.in new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/docs/version.xml.in @@ -0,0 +1 @@ +@VERSION@ diff --git a/docs/xdg-hostname-docs.xml b/docs/xdg-hostname-docs.xml new file mode 100644 index 0000000..52d5f5c --- /dev/null +++ b/docs/xdg-hostname-docs.xml @@ -0,0 +1,486 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +<!ENTITY version SYSTEM "version.xml"> +]> +<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude"> + <bookinfo> + <title>xdg-hostname Reference Manual</title> + <releaseinfo>Version &version;</releaseinfo> + <authorgroup> + <author> + <firstname>David</firstname> + <surname>Zeuthen</surname> + <affiliation> + <address> + <email>davidz@redhat.com</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2008</year> + <holder>The xdg-hostname Authors</holder> + </copyright> + + <legalnotice> + <para> + Permission is granted to copy, distribute and/or modify this + document under the terms of the <citetitle>GNU Free + Documentation License</citetitle>, Version 1.1 or any later + version published by the Free Software Foundation with no + Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. You may obtain a copy of the <citetitle>GNU Free + Documentation License</citetitle> from the Free Software + Foundation by visiting <ulink type="http" + url="http://www.fsf.org">their Web site</ulink> or by writing + to: + + <address> + The Free Software Foundation, Inc., + <street>59 Temple Place</street> - Suite 330, + <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>, + <country>USA</country> + </address> + </para> + + <para> + Many of the names used by companies to distinguish their + products and services are claimed as trademarks. Where those + names appear in any freedesktop.org documentation, and those trademarks + are made aware to the members of the freedesktop.org + Project, the names have been printed in caps or initial caps. + </para> + </legalnotice> + </bookinfo> + + <reference id="overview"> + <title>Overview</title> + <chapter id="overview-introduction"> + <title>Introduction</title> + <para> + The <literal>xdg-hostname</literal> project provides a + mechanism to get, set and monitor changes for hostname + data. Hostname data is defined to include more than just the + regular hostname, it also includes a display hostname, an icon + and possibly more items in the future. Hostname data is + usually a user preference and is stored in a persistent local + database. + </para> + <para> + In addition, the <literal>xdg-hostname</literal> project + provides a facility for network configuration software to + inject transient hostname data that, according to user + preference, can take precedence over local configuration data. + For example, when a system obtains network configuration + data via + <ulink url="http://en.wikipedia.org/wiki/Dhcp">DHCP</ulink>, + auxiliary data as defined by + <ulink url="http://tools.ietf.org/rfc/rfc2132.txt">RFC 2132</ulink> + may specify what hostname to use. + </para> + <para> + The main audience for the <literal>xdg-hostname</literal> + project include + <itemizedlist> + <listitem> + <para> + Desktop environments - for displaying and allowing + the user to configure hostname data. + </para> + </listitem> + <listitem> + <para> + Applications exporting named services on the + network. Such applications can consume hostname + data to provide a more useful name for the service + they export. + </para> + </listitem> + </itemizedlist> + The main benefit from using hostname data provided by the + <literal>xdg-hostname</literal> project is the display + hostname. Compared to the traditional hostname (which + normally conforms to section 3.5 of + <ulink url="http://www.ietf.org/rfc/rfc1034.txt">RFC 1034</ulink> + with the hostname being a label: 7 bit ASCII without special characters, + whitespace or dots) the display hostname is UTF-8. + </para> + <para> + Applications can use the display hostname announcing + services via e.g. + <ulink url="http://en.wikipedia.org/wiki/DNS-SD">DNS-SD</ulink>. + For example, a file sharing application may use set the service name to + "David's files on Kitchen Computer" (or in Chinese "David' 在厨 + 房计算机上的s文件") instead of the uglier + and less meaningful name "David's files on localhost". + </para> + <para> + In addition, this service introduces the concept of + associating an icon with a system. This is useful for + applications announcing services on the network. For example, + for DNS-SD, a TXT record may be set to the icon name. Icon + names are designed to conform to the freedesktop.org + <ulink url="http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html">Icon Theme Specification</ulink> + and + <ulink url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">Icon Naming Specification</ulink> + specifications. + </para> + <para> + It is important to understand that the display hostname and + hostname are different on a conceptual level; many of the + the observations in section 4.4 of the + <ulink url="http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt">DNS-SD + Draft</ulink> applies here. Specifically, the display hostname is, + among other things, intended to be used for naming services + (e.g. "Recipes on Kitchen Computer") announced via e.g. DNS-SD + and the hostname (e.g. "t41-davidz") is for identifying the + system on which software providing the service runs. One way + to think about this is that the display hostname represents what + the system <emphasis>does</emphasis> while the hostname + represents what the system <emphasis>is</emphasis>. + </para> + <para> + For example, if the system with the hostname "t41-davidz" is + replaced by a another system with the hostname "x61-davidz" it + is useful to keep the display hostname the same ("Kitchen + Computer") such that users on the network consuming services + ("Recipes on Kitchen Computer") won't need to be reconfigured. + </para> + <para> + The display hostname is what should be presented in the user + interface; users (who are not administrators) should never ever + need to see the hostname. + </para> + </chapter> + + <chapter id="overview-reading"> + <title>Reading hostname data</title> + <para> + Hostname data exported by the <literal>xdg-hostname</literal> + project is available via a D-Bus service on the system message + bus. To access the D-Bus service, use the well-known + name <literal>org.freedesktop.Hostname1</literal> on the D-Bus + system message bus and connect to the + interface + <xref linkend="Hostname1"/> + for the + object at the + path <literal>/org/freedesktop/hostname1</literal>. + </para> + <para> + For reading hostname data, simply read the D-Bus properties, e.g. + <link linkend="Hostname1:display-hostname">display-hostname</link>, + <link linkend="Hostname1:hostname">hostname</link> and + <link linkend="Hostname1:icon-name">icon-name</link>. To listen for changes, + connect to the + <link linkend="Hostname1::Changed">Changed()</link> signal. + </para> + <para> + The value of these properties are usually computed using the following algorithm: + <itemizedlist> + <listitem> + <para> + For + <link linkend="Hostname1:hostname">hostname</link>, + if + <link linkend="Hostname1:use-transient-data">use-transient-data</link> + data is <literal>TRUE</literal> and a live transient data provider + is registered (see <xref linkend="overview-providing-transient-data"/>), then + <link linkend="Hostname1:transient-hostname">transient-hostname</link> is returned + if the property is not the empty string. + Otherwise + <link linkend="Hostname1:configured-hostname">configured-hostname</link> + is returned. + </para> + </listitem> + </itemizedlist> + Likewise for the + <link linkend="Hostname1:display-hostname">display-hostname</link> and + <link linkend="Hostname1:icon-name">icon-name</link> properties. + </para> + <para> + Applications MUST NOT assume this algorithm is used. An + implementation of the <literal>org.freedesktop.Hostname1</literal> + D-Bus service MAY use another algorithm to return hostname + data (for example, an implementation may read the hostname + data from e.g. a + <ulink url="http://en.wikipedia.org/wiki/LDAP">LDAP</ulink>, + another implementation may read it from + <ulink url="http://en.wikipedia.org/wiki/Vital_Product_Data">Vital Product Data</ulink> + etc.) + </para> + </chapter> + + <chapter id="overview-configuring"> + <title>Configuring hostname data</title> + <para> + System configuration tools should use the methods + <link linkend="Hostname1.SetDisplayHostname">SetDisplayHostname()</link>, + <link linkend="Hostname1.SetHostname">SetHostname()</link>, + <link linkend="Hostname1.SetIconName">SetIconName()</link> and + <link linkend="Hostname1.SetUseTransientData">SetUseTransientData()</link>, + method to set data. + </para> + <para> + Graphical user interfaces would also use the + <link linkend="Hostname1:configured-display-hostname">configured-display-hostname</link>, + <link linkend="Hostname1:configured-hostname">configured-hostname</link>, + <link linkend="Hostname1:configured-icon-name">configured-icon-name</link> and + <link linkend="Hostname1:use-transient-data">use-transient-data</link> + properties to initialize the user interface with currently configured values. + The + <link linkend="Hostname1:can-set-display-hostname">can-set-display-hostname</link>, + <link linkend="Hostname1:can-set-hostname">can-set-hostname</link>, + <link linkend="Hostname1:can-set-icon-name">can-set-icon-name</link> and + <link linkend="Hostname1:can-set-use-transient-data">can-set-use-transient-data</link> + properties can be used to determine what parts of the user interface is sensitive e.g + what can be changed. + </para> + <para> + As an example, one user interface could look like this + <informalexample> + <programlisting> + +---------+ + | Icon | Computer Name: [David's Kitchen Computer___________] + | Chooser | + +---------+ + To access this computer from the network use the name + davids-kitchen-computer.local + + [>] Advanced + + [Revert] [Cancel] [Apply] + </programlisting> + </informalexample> + where the hostname is automatically computed from the display + hostname. If the user wants to explicitly set the hostname + he can expand the dialog: + <informalexample> + <programlisting> + +---------+ + | Icon | Computer Name: [David's Kitchen Computer___________] + | Chooser | + +---------+ + To access this computer from the network use the name + x61-davidz.local + + [V] Advanced + + Hostname: [x61-davidz_________________________] + + [ ] Always change hostname if provided by network connections + + [Revert] [Cancel] [Apply] + </programlisting> + </informalexample> + In addition, the "Always change hostname if provided by + network connections" element represents the + <link linkend="Hostname1:use-transient-data">use-transient-data</link> + property. + </para> + </chapter> + + <chapter id="overview-providing-transient-data"> + <title>Providing transient data</title> + <para> + Networking configuration tools should use the + <link linkend="Hostname1.RegisterTransientDataProvider">RegisterTransientDataProvider()</link> + method when connecting to a network where a hostname is provided as part of the + connection setup. + </para> + <para> + Using the obtained cookie, the network configuration tool + can invoke methods such as + <link linkend="Hostname1.SetTransientHostname">SetTransientHostname()</link> + to e.g. set the hostname. + If hostname data changes over time (for example, when renewing a DHCP lease), the + network configuration tool can simply call + <link linkend="Hostname1.SetTransientHostname">SetTransientHostname()</link> + again. + </para> + <para> + When disconnecting from the network, the networking configuration tool must call + <link linkend="Hostname1.UnregisterTransientDataProvider">UnregisterTransientDataProvider()</link>. + </para> + <para> + A provider of transient hostname data should ALWAYS supply + data this way even + if <link linkend="Hostname1:use-transient-data">use-transient-data</link> + is <literal>FALSE</literal>. + </para> + </chapter> + + <chapter id="overview-implementation-details"> + <title>Implementation Details</title> + <para> + This section describes implementation details about the software + shipped as part of the <literal>xdg-hostname</literal> project. Applications + MUST NOT rely on these implementation details as other software + may provide <literal>org.freedesktop.Hostname1</literal> D-Bus service. + This information is provided only to make it easier for vendors + to integrate the <literal>xdg-hostname</literal> project into + operating system products. + </para> + <para> + The <literal>org.freedesktop.Hostname1</literal> D-Bus service + is designed to be implemented by a process launched on demand + using D-Bus system bus activation. In addition, after 30 + seconds of inactivity (e.g. no method calls or transient data providers), the process + providing the D-Bus service will automatically exit and + release resources. The + <xref linkend="xdg-hostnamed-1.8"/> + daemon is used to provide + the <literal>org.freedesktop.Hostname1</literal> D-Bus + service. + </para> + <para> + For easy access to the <literal>org.freedesktop.Hostname1</literal> + D-Bus service, the + <xref linkend="xdg-hostname-1.1"/> + program is provided. + In addition to configuring hostname data, this program + provides direct access to the local configuration database + without using D-Bus. This is useful in sitations where no + system bus is available, for example early user space or when + configuring a system or image in + a <literal>chroot(1)</literal> environment. + </para> + <para> + If the hostname is manually set (e.g. not using the + <literal>org.freedesktop.Hostname1</literal> D-Bus service), + the + <xref linkend="xdg-hostname-1.1"/> + program should be used to update the local database of the + <literal>xdg-hostname</literal> project: + <informalexample> +<programlisting> +xdg-hostname-1 --set-hostname `/bin/hostname` +</programlisting> + </informalexample> + </para> + <para> + If even this doesn't happen, + <xref linkend="xdg-hostnamed-1.8"/> + will always compare the result + of <literal>gethostname(2)</literal> + with what's in the local database before every operation + (e.g. setting or returning + <link linkend="Hostname1:hostname">hostname</link> and other + properties). + If there's a mismatch it means the hostname was manually changed + without invoking + <xref linkend="xdg-hostname-1.1"/> + as described above. + As a result, + <xref linkend="xdg-hostnamed-1.8"/> + will update the local database to match the current + hostname as returned by <literal>gethostname(2)</literal>. + The only change is that change notifications on + the D-Bus interface are delayed. + </para> + <para> + Changing the hostname on a <literal>UNIX</literal> system + can a bit more work than just invoking the + the <literal>sethostname(2)</literal> system call. + Depending on the operating system, other actions, + such as updating one or more configuration files, may need to + happen. To accommodate this, all executable programs in the + <literal>/etc/xdg-hostname-1/run.d</literal> + directory with the extension <literal>.run</literal> + will be invoked (sequentially, in the C locale's alphabetical order) + by + <xref linkend="xdg-hostnamed-1.8"/> + whenever one of the + <link linkend="Hostname1:display-hostname">display-hostname</link>, + <link linkend="Hostname1:hostname">hostname</link> and + <link linkend="Hostname1:icon-name">icon-name</link> + properties change. Two positional parameters will be supplied, + the first is the name of the property (e.g: <literal>display-hostname</literal>), + the second being it's value (e.g.: <literal>Jukebox ♫♫♫</literal>). + The exit code of the programs are ignored. If a program invoked + this way hasn't exited within 5 seconds, it will be silently + killed and an error will be logged. While the <literal>.run</literal> + programs are being run, + <xref linkend="xdg-hostnamed-1.8"/> + will not service requests on the D-Bus interface (requests will be queued + up for processing when all the <literal>.run</literal> programs have run). + </para> + <para> + A number of applications require that the name returned by + <literal>gethostname(2)</literal> resolves to the local + machine (typically 127.0.0.1). This can be achieved via + either using a <literal>.run</literal> script in <literal>/etc/xdg-hostname-1/run.d</literal> that updates + the <literal>/etc/hosts</literal> file + or through a + <ulink url="http://en.wikipedia.org/wiki/GNU_C_Library">GNU C Library</ulink> + extension such as + <ulink url="http://0pointer.de/lennart/projects/nss-myhostname/README.txt">nss-myhostname</ulink>. + </para> + <para> + Typically, when booting a <literal>UNIX</literal> system the + hostname needs to be set as early as possible. As an implementation + detail, + <xref linkend="xdg-hostnamed-1.8"/> + will always attempt write the current hostname (e.g. the value + of the + <link linkend="Hostname1:hostname">hostname</link> + property) to the <literal>/etc/xdg-hostname-1/hostname</literal> + file (specifically this file may be a symlink to e.g. the + <literal>/etc/hostname</literal> file). + Operating system boot scripts may use the contents of this + file to set the hostname when booting. + </para> + </chapter> + + </reference> + + <reference id="ref-dbus"> + <title>D-Bus API Reference</title> + <partintro> + <para> + This part documents the D-Bus interface used to access the + <literal>xdg-hostname</literal> project. + </para> + </partintro> + <xi:include href="dbus/org.freedesktop.Hostname1.ref.xml"/> + </reference> + + <reference id="ref-gobject"> + <title>GObject API Reference</title> + <partintro> + <para> + This part documents a GObject library used to access the + <literal>xdg-hostname</literal> project. + </para> + </partintro> + <xi:include href="xml/xdghostnamemonitor.xml"/> + <xi:include href="xml/xdghostnameerror.xml"/> + </reference> + + <reference id="ref-tools"> + <title>Tools</title> + <partintro> + <para> + This part presents the tools distributed with the. + <literal>xdg-hostname</literal> project. + </para> + </partintro> + <xi:include href="man/xdg-hostname-1.xml"/> + <xi:include href="man/xdg-hostnamed-1.xml"/> + </reference> + + <index> + <title>Index</title> + </index> + + <!-- License --> + + <appendix id="license"> + <title>License</title> + <para> +<programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../COPYING" parse="text"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting> + </para> + </appendix> +</book> diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/po/ChangeLog diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..b72d517 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,4 @@ +# please keep this list sorted alphabetically +# + + diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..af5c522 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,4 @@ +# List of source files containing translatable strings. +# Please keep this file sorted alphabetically. +[encoding: UTF-8] +policy/org.freedesktop.hostname1.policy.in diff --git a/policy/Makefile.am b/policy/Makefile.am new file mode 100644 index 0000000..e3447e3 --- /dev/null +++ b/policy/Makefile.am @@ -0,0 +1,17 @@ + +hostname1_policydir = $(datadir)/PolicyKit/policy + +dist_hostname1_policy_DATA = \ + org.freedesktop.hostname1.policy + +@INTLTOOL_POLICY_RULE@ + +check: + polkit-policy-file-validate $(top_srcdir)/policy/$(dist_hostname1_policy_DATA) + +clean-local : + rm -f *~ *.policy + +DISTCLEANFILES = $(dist_hostname1_policy_DATA) + +EXTRA_DIST = $(dist_hostname1_policy_DATA:.policy=.policy.in) diff --git a/policy/org.freedesktop.hostname1.policy.in b/policy/org.freedesktop.hostname1.policy.in new file mode 100644 index 0000000..5832831 --- /dev/null +++ b/policy/org.freedesktop.hostname1.policy.in @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!DOCTYPE policyconfig PUBLIC + "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" + "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> + +<!-- +Policy definitions for xdg-hostname + +Copyright (c) 2008 David Zeuthen <davidz@redhat.com>. Licensed under LGPLv2+. + +--> + +<policyconfig> + <vendor>The xdg-hostname Project</vendor> + + <action id="org.freedesktop.hostname1.change"> + <_description>Change hostname data</_description> + <_message>Authentication is required to change the hostname</_message> + <defaults> + <allow_any>no</allow_any> + <allow_inactive>no</allow_inactive> + <allow_active>auth_self</allow_active> + </defaults> + </action> + +</policyconfig> diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..879c664 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,5 @@ + +SUBDIRS = xdghostname daemon programs + +clean-local : + rm -f *~ diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am new file mode 100644 index 0000000..a43703c --- /dev/null +++ b/src/daemon/Makefile.am @@ -0,0 +1,51 @@ +NULL = + +INCLUDES = \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_REENTRANT \ + $(NULL) + +BUILT_SOURCES = \ + xdghostnamedaemonglue.h \ + $(NULL) + +xdghostnamedaemonglue.h: $(top_srcdir)/data/org.freedesktop.Hostname1.xml Makefile.am + dbus-binding-tool --prefix=_xdg_hostname_daemon --mode=glib-server --output=xdghostnamedaemonglue.h $(top_srcdir)/data/org.freedesktop.Hostname1.xml + +libexec_PROGRAMS = xdg-hostname-daemon-1 + +xdg_hostname_daemon_1_SOURCES = \ + main.c \ + xdghostnamedaemon.c xdghostnamedaemon.h \ + $(NULL) + +xdg_hostname_daemon_1_CFLAGS = \ + -I$(top_srcdir)/src \ + -DG_LOG_DOMAIN=\"xdg-hostname-daemon-1\" \ + $(DBUS_GLIB_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(NULL) + +xdg_hostname_daemon_1_LDADD = \ + $(DBUS_GLIB_LIBS) \ + $(GLIB_LIBS) \ + $(GIO_LIBS) \ + $(POLKIT_LIBS) \ + $(top_builddir)/src/xdghostname/libxdg-hostname-gobject-1.la \ + $(NULL) + +CLEANFILES = $(BUILT_SOURCES) + +clean-local : + rm -f *~ diff --git a/src/daemon/main.c b/src/daemon/main.c new file mode 100644 index 0000000..34f8dc0 --- /dev/null +++ b/src/daemon/main.c @@ -0,0 +1,175 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 David Zeuthen <david@fubar.dk> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pwd.h> +#include <grp.h> + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <glib-object.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include "xdghostnamedaemon.h" + +#define NAME_TO_CLAIM "org.freedesktop.Hostname1" + +static gboolean +acquire_name_on_proxy (DBusGProxy *bus_proxy) +{ + GError *error; + guint result; + gboolean res; + gboolean ret; + + ret = FALSE; + + if (bus_proxy == NULL) { + goto out; + } + + error = NULL; + res = dbus_g_proxy_call (bus_proxy, + "RequestName", + &error, + G_TYPE_STRING, NAME_TO_CLAIM, + G_TYPE_UINT, 0, + G_TYPE_INVALID, + G_TYPE_UINT, &result, + G_TYPE_INVALID); + if (! res) { + if (error != NULL) { + g_warning ("Failed to acquire %s: %s", NAME_TO_CLAIM, error->message); + g_error_free (error); + } else { + g_warning ("Failed to acquire %s", NAME_TO_CLAIM); + } + goto out; + } + + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + if (error != NULL) { + g_warning ("Failed to acquire %s: %s", NAME_TO_CLAIM, error->message); + g_error_free (error); + } else { + g_warning ("Failed to acquire %s", NAME_TO_CLAIM); + } + goto out; + } + + ret = TRUE; + + out: + return ret; +} + +int +main (int argc, char **argv) +{ + GError *error; + GMainLoop *loop; + GOptionContext *context; + DBusGProxy *bus_proxy; + DBusGConnection *bus; + int ret; + XdgHostnameDaemon *daemon; + static GOptionEntry entries[] = { + { NULL } + }; + + ret = 1; + daemon = NULL; + loop = NULL; + bus = NULL; + + g_type_init (); + + context = g_option_context_new ("xdg-hostname-daemon-1"); + g_option_context_add_main_entries (context, entries, NULL); + g_option_context_parse (context, &argc, &argv, NULL); + g_option_context_free (context); + + error = NULL; + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (bus == NULL) { + g_warning ("Couldn't connect to system bus: %s", error->message); + g_error_free (error); + goto out; + } + + bus_proxy = dbus_g_proxy_new_for_name (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + if (bus_proxy == NULL) { + g_warning ("Could not construct bus_proxy object; bailing out"); + goto out; + } + + if (!acquire_name_on_proxy (bus_proxy) ) { + g_warning ("Could not acquire name; bailing out"); + goto out; + } + + g_debug ("Starting xdg-hostname-daemon-1 version %s", VERSION); + + daemon = xdg_hostname_daemon_new (bus, "/org/freedesktop/hostname1"); + + if (daemon == NULL) { + goto out; + } + + loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (loop); + + ret = 0; + +out: + if (daemon != NULL) + g_object_unref (daemon); + + if (loop != NULL) + g_main_loop_unref (loop); + + if (bus != NULL) + dbus_g_connection_unref (bus); + + return ret; +} diff --git a/src/daemon/xdghostnamedaemon.c b/src/daemon/xdghostnamedaemon.c new file mode 100644 index 0000000..6877ff7 --- /dev/null +++ b/src/daemon/xdghostnamedaemon.c @@ -0,0 +1,1140 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include "config.h" + +#include <errno.h> +#include <unistd.h> +#include <string.h> + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <glib-object.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include <polkit-dbus/polkit-dbus.h> + +#include <xdghostname/xdghostname.h> + +#include "xdghostnamedaemon.h" + +struct _XdgHostnameDaemon +{ + GObject parent_instance; + + char *display_hostname; + char *hostname; + char *icon_name; + + char *configured_display_hostname; /* may include more than one label */ + char *configured_hostname; + char *configured_icon_name; + + gboolean use_transient_data; + + char *transient_display_hostname; + char *transient_hostname; + char *transient_icon_name; + + gboolean can_set_display_hostname; + gboolean can_set_hostname; + gboolean can_set_icon_name; + gboolean can_set_use_transient_data; + + + gboolean inhibit_reading; + + DBusConnection *system_bus_connection; + PolKitContext *pk_context; +}; + +struct _XdgHostnameDaemonClass +{ + GObjectClass parent_class; +}; + +enum { + CHANGED_SIGNAL, + LAST_SIGNAL, +}; + +enum { + PROP_0, + + PROP_DISPLAY_HOSTNAME, + PROP_HOSTNAME, + PROP_ICON_NAME, + + PROP_CONFIGURED_DISPLAY_HOSTNAME, + PROP_CONFIGURED_HOSTNAME, + PROP_CONFIGURED_ICON_NAME, + PROP_USE_TRANSIENT_DATA, + + PROP_TRANSIENT_DISPLAY_HOSTNAME, + PROP_TRANSIENT_HOSTNAME, + PROP_TRANSIENT_ICON_NAME, + + PROP_CAN_SET_DISPLAY_HOSTNAME, + PROP_CAN_SET_HOSTNAME, + PROP_CAN_SET_ICON_NAME, + PROP_CAN_SET_USE_TRANSIENT_DATA, +}; + + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (XdgHostnameDaemon, xdg_hostname_daemon, G_TYPE_OBJECT) + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean update_data (XdgHostnameDaemon *daemon, + gboolean emit_changed_signal, + GError **error); + +static char *extract_first_label (const char *name); + +/*--------------------------------------------------------------------------------------------------------------*/ + +/* exported methods */ + +static gboolean _xdg_hostname_daemon_set_display_hostname (XdgHostnameDaemon *hostname_daemon, + const char *display_hostname, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_set_hostname (XdgHostnameDaemon *hostname_daemon, + const char *hostname, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_set_icon_name (XdgHostnameDaemon *hostname_daemon, + const char *icon_name, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_set_use_transient_data (XdgHostnameDaemon *hostname_daemon, + gboolean use_transient_data, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_set_transient_display_hostname (XdgHostnameDaemon *hostname_daemon, + const char *cookie, + const char *display_hostname, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_set_transient_hostname (XdgHostnameDaemon *hostname_daemon, + const char *cookie, + const char *hostname, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_set_transient_icon_name (XdgHostnameDaemon *hostname_daemon, + const char *cookie, + const char *icon_name, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_register_transient_data_provider (XdgHostnameDaemon *hostname_daemon, + DBusGMethodInvocation *context); + +static gboolean _xdg_hostname_daemon_unregister_transient_data_provider (XdgHostnameDaemon *hostname_daemon, + const char *cookie, + DBusGMethodInvocation *context); + +#include "xdghostnamedaemonglue.h" + +/*--------------------------------------------------------------------------------------------------------------*/ + +static void +xdg_hostname_daemon_init (XdgHostnameDaemon *daemon) +{ +} + +static void +xdg_hostname_daemon_constructed (GObject *object) +{ + XdgHostnameDaemon *daemon; + GError *error; + + g_return_if_fail (XDG_IS_HOSTNAME_DAEMON (object)); + + daemon = XDG_HOSTNAME_DAEMON (object); + + /* we don't support any lock down other than polkit for now (or ever) */ + daemon->can_set_display_hostname = TRUE; + daemon->can_set_hostname = TRUE; + daemon->can_set_icon_name = TRUE; + daemon->can_set_use_transient_data = TRUE; + + error = NULL; + if (!update_data (daemon, FALSE, &error)) { + g_warning ("Error updating data: %s", error->message); + g_error_free (error); + } + + if (G_OBJECT_CLASS (xdg_hostname_daemon_parent_class)->constructed != NULL) + G_OBJECT_CLASS (xdg_hostname_daemon_parent_class)->constructed (object); +} + +static void +xdg_hostname_daemon_finalize (GObject *object) +{ + XdgHostnameDaemon *daemon; + + g_return_if_fail (XDG_IS_HOSTNAME_DAEMON (object)); + + daemon = XDG_HOSTNAME_DAEMON (object); + + g_free (daemon->display_hostname); + g_free (daemon->hostname); + g_free (daemon->icon_name); + + g_free (daemon->configured_display_hostname); + g_free (daemon->configured_hostname); + g_free (daemon->configured_icon_name); + + g_free (daemon->transient_display_hostname); + g_free (daemon->transient_hostname); + g_free (daemon->transient_icon_name); + + G_OBJECT_CLASS (xdg_hostname_daemon_parent_class)->finalize (object); +} + +static void +xdg_hostname_daemon_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + XdgHostnameDaemon *daemon; + GError *error; + char *label; + + g_return_if_fail (XDG_IS_HOSTNAME_DAEMON (object)); + + daemon = XDG_HOSTNAME_DAEMON (object); + + error = NULL; + if (!update_data (daemon, TRUE, &error)) { + g_warning ("Error updating data: %s", error->message); + g_error_free (error); + } + + switch (prop_id) { + case PROP_DISPLAY_HOSTNAME: + g_value_set_string (value, daemon->display_hostname); + break; + + case PROP_HOSTNAME: + /* The hostname may have several labels before we can get it + * from the kernel or from the /etc/xdg-hostname-1/hostname + * file that the user may manually edit. + * + * However, only return the first label to the user, anything + * else doesn't make any sense. + */ + label = extract_first_label (daemon->hostname); + g_value_set_string (value, label); + g_free (label); + break; + + case PROP_ICON_NAME: + g_value_set_string (value, daemon->icon_name); + break; + + case PROP_CONFIGURED_DISPLAY_HOSTNAME: + g_value_set_string (value, daemon->configured_display_hostname); + break; + + case PROP_CONFIGURED_HOSTNAME: + g_value_set_string (value, daemon->configured_hostname); + break; + + case PROP_CONFIGURED_ICON_NAME: + g_value_set_string (value, daemon->configured_icon_name); + break; + + case PROP_USE_TRANSIENT_DATA: + g_value_set_boolean (value, daemon->use_transient_data); + break; + + case PROP_TRANSIENT_DISPLAY_HOSTNAME: + g_value_set_string (value, daemon->transient_display_hostname); + break; + + case PROP_TRANSIENT_HOSTNAME: + g_value_set_string (value, daemon->transient_hostname); + break; + + case PROP_TRANSIENT_ICON_NAME: + g_value_set_string (value, daemon->transient_icon_name); + break; + + case PROP_CAN_SET_DISPLAY_HOSTNAME: + g_value_set_boolean (value, daemon->can_set_display_hostname); + break; + + case PROP_CAN_SET_HOSTNAME: + g_value_set_boolean (value, daemon->can_set_hostname); + break; + + case PROP_CAN_SET_ICON_NAME: + g_value_set_boolean (value, daemon->can_set_icon_name); + break; + + case PROP_CAN_SET_USE_TRANSIENT_DATA: + g_value_set_boolean (value, daemon->can_set_use_transient_data); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +xdg_hostname_daemon_class_init (XdgHostnameDaemonClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = xdg_hostname_daemon_finalize; + object_class->constructed = xdg_hostname_daemon_constructed; + object_class->get_property = xdg_hostname_daemon_get_property; + + /** + * XdgHostnameDaemon::changed: + * @daemon: The daemon. + * + * Emitted when one or more properties change. + */ + signals[CHANGED_SIGNAL] = g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_object_class_install_property (object_class, + PROP_DISPLAY_HOSTNAME, + g_param_spec_string ("display-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_HOSTNAME, + g_param_spec_string ("hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_ICON_NAME, + g_param_spec_string ("icon-name", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_CONFIGURED_DISPLAY_HOSTNAME, + g_param_spec_string ("configured-display-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_CONFIGURED_HOSTNAME, + g_param_spec_string ("configured-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_CONFIGURED_ICON_NAME, + g_param_spec_string ("configured-icon-name", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_USE_TRANSIENT_DATA, + g_param_spec_boolean ("use-transient-data", + NULL, + NULL, + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_TRANSIENT_DISPLAY_HOSTNAME, + g_param_spec_string ("transient-display-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_TRANSIENT_HOSTNAME, + g_param_spec_string ("transient-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_TRANSIENT_ICON_NAME, + g_param_spec_string ("transient-icon-name", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_CAN_SET_DISPLAY_HOSTNAME, + g_param_spec_boolean ("can-set-display-hostname", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_CAN_SET_HOSTNAME, + g_param_spec_boolean ("can-set-hostname", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_CAN_SET_ICON_NAME, + g_param_spec_boolean ("can-set-icon-name", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, + PROP_CAN_SET_USE_TRANSIENT_DATA, + g_param_spec_boolean ("can-set-use-transient-data", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + + dbus_g_error_domain_register (XDG_HOSTNAME_ERROR, + "org.freedesktop.Hostname1.Error", + XDG_HOSTNAME_TYPE_ERROR); + + dbus_g_object_type_install_info (XDG_TYPE_HOSTNAME_DAEMON, &dbus_glib__xdg_hostname_daemon_object_info); +} + +static gboolean +pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data) +{ + int fd; + PolKitContext *pk_context = user_data; + fd = g_io_channel_unix_get_fd (channel); + polkit_context_io_func (pk_context, fd); + return TRUE; +} + +static int +pk_io_add_watch (PolKitContext *pk_context, int fd) +{ + guint id = 0; + GIOChannel *channel; + channel = g_io_channel_unix_new (fd); + if (channel == NULL) + goto out; + id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context); + if (id == 0) { + g_io_channel_unref (channel); + goto out; + } + g_io_channel_unref (channel); +out: + return id; +} + +static void +pk_io_remove_watch (PolKitContext *pk_context, int watch_id) +{ + g_source_remove (watch_id); +} + +XdgHostnameDaemon * +xdg_hostname_daemon_new (DBusGConnection *connection, + const char *object_path) +{ + XdgHostnameDaemon *daemon; + + daemon = XDG_HOSTNAME_DAEMON (g_object_new (XDG_TYPE_HOSTNAME_DAEMON, NULL)); + + dbus_g_connection_register_g_object (connection, + object_path, + G_OBJECT (daemon)); + + daemon->system_bus_connection = dbus_g_connection_get_connection (connection); + + daemon->pk_context = polkit_context_new (); + polkit_context_set_io_watch_functions (daemon->pk_context, pk_io_add_watch, pk_io_remove_watch); + if (!polkit_context_init (daemon->pk_context, NULL)) { + g_warning ("cannot initialize libpolkit"); + goto error; + } + + return daemon; + + error: + g_object_unref (daemon); + return NULL; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_not_supported (XdgHostnameDaemon *daemon, + DBusGMethodInvocation *context) +{ + GError *error; + error = g_error_new_literal (XDG_HOSTNAME_ERROR, + XDG_HOSTNAME_ERROR_NOT_SUPPORTED, + "Not Supported"); + dbus_g_method_return_error (context, error); + g_error_free (error); + return TRUE; +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static char * +extract_first_label (const char *name) +{ + char *s; + char *ret; + + ret = NULL; + + if (name == NULL) + goto out; + + s = strchr (name, '.'); + if (s == NULL) + ret = g_strdup (name); + else + ret = g_strndup (name, s - name); + + out: + return ret; +} + + +static gboolean +uninhibit_reading (XdgHostnameDaemon *daemon) +{ + daemon->inhibit_reading = FALSE; + g_warning ("unihibiting reading"); + return FALSE; +} + +static char * +compute_val (XdgHostnameDaemon *daemon) +{ + GString *s; + + s = g_string_new (NULL); + if (daemon->display_hostname != NULL) + g_string_append (s, daemon->display_hostname); + else + g_string_append_c (s, ' '); + if (daemon->hostname != NULL) + g_string_append (s, daemon->hostname); + else + g_string_append_c (s, ' '); + if (daemon->icon_name != NULL) + g_string_append (s, daemon->icon_name); + else + g_string_append_c (s, ' '); + g_string_append_c (s, daemon->use_transient_data ? '1' : '0'); + + if (daemon->configured_display_hostname != NULL) + g_string_append (s, daemon->configured_display_hostname); + else + g_string_append_c (s, ' '); + if (daemon->configured_hostname != NULL) + g_string_append (s, daemon->configured_hostname); + else + g_string_append_c (s, ' '); + if (daemon->configured_icon_name != NULL) + g_string_append (s, daemon->configured_icon_name); + else + g_string_append_c (s, ' '); + + if (daemon->transient_display_hostname != NULL) + g_string_append (s, daemon->transient_display_hostname); + else + g_string_append_c (s, ' '); + if (daemon->transient_hostname != NULL) + g_string_append (s, daemon->transient_hostname); + else + g_string_append_c (s, ' '); + if (daemon->transient_icon_name != NULL) + g_string_append (s, daemon->transient_icon_name); + else + g_string_append_c (s, ' '); + + g_string_append_c (s, daemon->can_set_display_hostname ? '1' : '0'); + g_string_append_c (s, daemon->can_set_hostname ? '1' : '0'); + g_string_append_c (s, daemon->can_set_icon_name ? '1' : '0'); + g_string_append_c (s, daemon->can_set_use_transient_data ? '1' : '0'); + + return g_string_free (s, FALSE); +} + +static gboolean +update_data (XdgHostnameDaemon *daemon, + gboolean emit_changed_signal, + GError **error) +{ + char *buf; + gsize size; + gboolean ret; + GKeyFile *key_file; + GError *local_error; + char kernel_name[HOST_NAME_MAX + 1]; + gboolean have_transient_data; + char *pre; + char *post; + gboolean changed; + gboolean force_changed; + + ret = FALSE; + buf = NULL; + key_file = NULL; + local_error = NULL; + changed = FALSE; + force_changed = FALSE; + + pre = compute_val (daemon); + + /* only reread data once per mainloop slice to avoid rereading the same stuff on e.g. Properties.GetAll() */ + if (daemon->inhibit_reading) { + ret = TRUE; + goto out; + } + g_idle_add ((GSourceFunc) uninhibit_reading, daemon); + daemon->inhibit_reading = TRUE; + + if (gethostname (kernel_name, sizeof (kernel_name)) != 0) { + g_set_error (error, + XDG_HOSTNAME_ERROR, + XDG_HOSTNAME_ERROR_FAILED, + "Error calling gethostname(): %s", + strerror (errno)); + goto out; + } + + g_strstrip (kernel_name); + + if (g_file_get_contents (PACKAGE_SYSCONF_DIR "/xdg-hostname-1/hostname", + &buf, + &size, + &local_error)) { + + /* update the hostname file in the event the kernel got a new name... */ + if (strcmp (kernel_name, buf) != 0) { + + /* TODO: use syslog instead */ + g_warning ("gethostname(2) returned hostname '%s' and our configuration file " + "has hostname '%s'. " + "Updating /etc/xdg-hostname-1/hostname to use name from gethostname(2).", + kernel_name, + buf); + + g_free (buf); + buf = NULL; + + if (!g_file_set_contents (PACKAGE_SYSCONF_DIR "/xdg-hostname-1/hostname", + kernel_name, + strlen (kernel_name), + error)) { + goto out; + } + + force_changed = TRUE; + + daemon->configured_hostname = g_strdup (kernel_name);; + } else { + g_strstrip (buf); + g_free (daemon->configured_hostname); + daemon->configured_hostname = buf; + buf = NULL; + } + } else { + if (local_error->code != G_FILE_ERROR_NOENT) { + g_propagate_error (error, local_error); + } else { + g_error_free (local_error); + local_error = NULL; + } + } + + if (g_file_get_contents (PACKAGE_SYSCONF_DIR "/xdg-hostname-1/data", + &buf, + &size, + &local_error)) { + key_file = g_key_file_new (); + if (!g_key_file_load_from_data (key_file, + buf, + size, + G_KEY_FILE_NONE, + error)) { + goto out; + } + + g_free (daemon->configured_display_hostname); + daemon->configured_display_hostname = g_key_file_get_string (key_file, + "HostnameData", + "DisplayHostname", + NULL); + + g_free (daemon->configured_icon_name); + daemon->configured_icon_name = g_key_file_get_string (key_file, + "HostnameData", + "IconName", + NULL); + + daemon->use_transient_data = g_key_file_get_boolean (key_file, + "HostnameData", + "UseTransientData", + NULL); + + g_free (buf); + buf = NULL; + + } else { + if (local_error->code != G_FILE_ERROR_NOENT) { + g_propagate_error (error, local_error); + } else { + g_error_free (local_error); + local_error = NULL; + } + } + + ret = TRUE; + + out: + if (key_file != NULL) + g_key_file_free (key_file); + g_free (buf); + + have_transient_data = FALSE; // TODO + + /* compute the values to return */ + g_free (daemon->display_hostname); + g_free (daemon->hostname); + g_free (daemon->icon_name); + if (daemon->use_transient_data && have_transient_data) { + + if (daemon->transient_display_hostname != NULL && strlen (daemon->transient_display_hostname) > 0) + daemon->display_hostname = g_strdup (daemon->transient_display_hostname); + else + daemon->display_hostname = g_strdup (daemon->configured_display_hostname); + + if (daemon->transient_hostname != NULL && strlen (daemon->transient_hostname) > 0) + daemon->hostname = g_strdup (daemon->transient_hostname); + else + daemon->hostname = g_strdup (daemon->configured_hostname); + + if (daemon->transient_icon_name != NULL && strlen (daemon->transient_icon_name) > 0) + daemon->icon_name = g_strdup (daemon->transient_icon_name); + else + daemon->icon_name = g_strdup (daemon->configured_icon_name); + + } else { + daemon->display_hostname = g_strdup (daemon->configured_display_hostname); + daemon->hostname = g_strdup (daemon->configured_hostname); + daemon->icon_name = g_strdup (daemon->configured_icon_name); + } + + post = compute_val (daemon); + if (strcmp (pre, post) != 0) + changed = TRUE; + g_free (pre); + g_free (post); + + /* we want to force a changed signal if the kernel's hostname changed under us */ + if (force_changed || (changed && emit_changed_signal)) + g_signal_emit (daemon, signals[CHANGED_SIGNAL], 0); + + g_print ("hostname: '%s'\n", daemon->hostname); + g_print ("display_hostname: '%s'\n", daemon->display_hostname); + g_print ("icon_name: '%s'\n", daemon->icon_name); + g_print ("configured_hostname: '%s'\n", daemon->configured_hostname); + g_print ("configured_display_hostname: '%s'\n", daemon->configured_display_hostname); + g_print ("configured_icon_name: '%s'\n", daemon->configured_icon_name); + g_print ("use_transient_data: %d\n", daemon->use_transient_data); + g_print ("transient_hostname: '%s'\n", daemon->transient_hostname); + g_print ("transient_display_hostname: '%s'\n", daemon->transient_display_hostname); + g_print ("transient_icon_name: '%s'\n", daemon->transient_icon_name); + g_print ("changed: %d (emit=%d force_emit=%d)\n", changed, emit_changed_signal, force_changed); + + return ret; +} + +typedef enum { + SET_DISPLAY_HOSTNAME = 0x01, + SET_HOSTNAME = 0x02, + SET_ICON_NAME = 0x04, + SET_USE_TRANSIENT_DATA = 0x08, +} SetDataFlags; + +static gboolean +_xdg_hostname_priv_set_data (SetDataFlags flags, + const char *display_hostname, + const char *hostname, + const char *icon_name, + gboolean use_transient_data, + GError **error) +{ + char *buf; + gsize size; + gboolean ret; + GError *local_error; + + ret = FALSE; + + /* TODO: sanity check data */ + + if (flags & SET_HOSTNAME) { + if (!g_file_set_contents (PACKAGE_SYSCONF_DIR "/xdg-hostname-1/hostname", + hostname, + strlen (hostname), + error)) { + goto out; + } + + if (sethostname (hostname, strlen (hostname)) != 0) { + g_set_error (error, + XDG_HOSTNAME_ERROR, + XDG_HOSTNAME_ERROR_FAILED, + "Error calling sethostname(): %s", + strerror (errno)); + goto out; + } + } + + if (flags & (SET_DISPLAY_HOSTNAME | + SET_ICON_NAME | + SET_USE_TRANSIENT_DATA)) { + GKeyFile *key_file; + + key_file = g_key_file_new (); + if (!g_file_get_contents (PACKAGE_SYSCONF_DIR "/xdg-hostname-1/data", + &buf, + &size, + &local_error)) { + if (local_error->code != G_FILE_ERROR_NOENT) { + g_key_file_free (key_file); + g_propagate_error (error, local_error); + goto out; + } + g_error_free (local_error); + local_error = NULL; + buf = NULL; + size = 0; + } else { + key_file = g_key_file_new (); + if (!g_key_file_load_from_data (key_file, + buf, + size, + G_KEY_FILE_KEEP_COMMENTS | + G_KEY_FILE_KEEP_TRANSLATIONS, + error)) { + g_free (buf); + g_key_file_free (key_file); + goto out; + } + } + g_free (buf); + + if (flags & SET_DISPLAY_HOSTNAME) { + g_key_file_set_string (key_file, + "HostnameData", + "DisplayHostname", + display_hostname); + } + + if (flags & SET_ICON_NAME) { + g_key_file_set_string (key_file, + "HostnameData", + "IconName", + icon_name); + } + + if (flags & SET_USE_TRANSIENT_DATA) { + g_key_file_set_boolean (key_file, + "HostnameData", + "UseTransientData", + use_transient_data); + } + + buf = g_key_file_to_data (key_file, + &size, + error); + if (buf == NULL) { + g_key_file_free (key_file); + goto out; + } + + if (!g_file_set_contents (PACKAGE_SYSCONF_DIR "/xdg-hostname-1/data", + buf, + strlen (buf), + error)) { + g_free (buf); + g_key_file_free (key_file); + goto out; + } + g_key_file_free (key_file); + g_free (buf); + + } + + ret = TRUE; + + out: + return ret; +} + +static gboolean +check_polkit_auth (XdgHostnameDaemon *daemon, + DBusGMethodInvocation *context) +{ + gboolean ret; + GError *error; + DBusError d_error; + PolKitAction *pk_action; + PolKitCaller *pk_caller; + PolKitResult pk_result; + const char *sender; + + ret = FALSE; + pk_caller = NULL; + pk_action = NULL; + + sender = dbus_g_method_get_sender (context); + + dbus_error_init (&d_error); + pk_caller = polkit_caller_new_from_dbus_name (daemon->system_bus_connection, + sender, + &d_error); + if (pk_caller == NULL) { + error = NULL; + dbus_set_g_error (&error, &d_error); + dbus_g_method_return_error (context, error); + g_error_free (error); + dbus_error_free (&d_error); + goto out; + } + + pk_action = polkit_action_new (); + polkit_action_set_action_id (pk_action, "org.freedesktop.hostname1.change"); + pk_result = polkit_context_is_caller_authorized (daemon->pk_context, + pk_action, + pk_caller, + TRUE, + NULL); + if (pk_result == POLKIT_RESULT_YES) { + ret = TRUE; + } else { + dbus_error_init (&d_error); + polkit_dbus_error_generate (pk_action, pk_result, &d_error); + error = NULL; + dbus_set_g_error (&error, &d_error); + dbus_g_method_return_error (context, error); + g_error_free (error); + dbus_error_free (&d_error); + } + + out: + if (pk_caller != NULL) + polkit_caller_unref (pk_caller); + if (pk_action != NULL) + polkit_action_unref (pk_action); + return ret; +} + +static gboolean +set_data (XdgHostnameDaemon *daemon, + SetDataFlags flags, + const char *display_hostname, + const char *hostname, + const char *icon_name, + gboolean use_transient_data, + DBusGMethodInvocation *context) +{ + GError *error; + + if (!check_polkit_auth (daemon, context)) + goto out; + + error = NULL; + if (!_xdg_hostname_priv_set_data (flags, + display_hostname, + hostname, + icon_name, + use_transient_data, + &error)) { + dbus_g_method_return_error (context, error); + g_error_free (error); + } else { + dbus_g_method_return (context); + } + + update_data (daemon, TRUE, &error); + + out: + return TRUE; +} + +/*--------------------------------------------------------------------------------------------------------------*/ +/* exported methods */ + +static gboolean +_xdg_hostname_daemon_set_display_hostname (XdgHostnameDaemon *daemon, + const char *display_hostname, + DBusGMethodInvocation *context) +{ + return set_data (daemon, + SET_DISPLAY_HOSTNAME, + display_hostname, + NULL, + NULL, + FALSE, + context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_set_hostname (XdgHostnameDaemon *daemon, + const char *hostname, + DBusGMethodInvocation *context) +{ + return set_data (daemon, + SET_HOSTNAME, + NULL, + hostname, + NULL, + FALSE, + context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_set_icon_name (XdgHostnameDaemon *daemon, + const char *icon_name, + DBusGMethodInvocation *context) +{ + return set_data (daemon, + SET_ICON_NAME, + NULL, + NULL, + icon_name, + FALSE, + context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_set_use_transient_data (XdgHostnameDaemon *daemon, + gboolean use_transient_data, + DBusGMethodInvocation *context) +{ + return set_data (daemon, + SET_USE_TRANSIENT_DATA, + NULL, + NULL, + NULL, + use_transient_data, + context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_set_transient_display_hostname (XdgHostnameDaemon *daemon, + const char *cookie, + const char *display_hostname, + DBusGMethodInvocation *context) +{ + return _not_supported (daemon, context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_set_transient_hostname (XdgHostnameDaemon *daemon, + const char *cookie, + const char *hostname, + DBusGMethodInvocation *context) +{ + return _not_supported (daemon, context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_set_transient_icon_name (XdgHostnameDaemon *daemon, + const char *cookie, + const char *icon_name, + DBusGMethodInvocation *context) +{ + return _not_supported (daemon, context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_register_transient_data_provider (XdgHostnameDaemon *daemon, + DBusGMethodInvocation *context) +{ + return _not_supported (daemon, context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ + +static gboolean +_xdg_hostname_daemon_unregister_transient_data_provider (XdgHostnameDaemon *daemon, + const char *cookie, + DBusGMethodInvocation *context) +{ + return _not_supported (daemon, context); +} + +/*--------------------------------------------------------------------------------------------------------------*/ diff --git a/src/daemon/xdghostnamedaemon.h b/src/daemon/xdghostnamedaemon.h new file mode 100644 index 0000000..a050fe4 --- /dev/null +++ b/src/daemon/xdghostnamedaemon.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifndef __XDG_HOSTNAME_DAEMON_H__ +#define __XDG_HOSTNAME_DAEMON_H__ + +#include <glib-object.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +G_BEGIN_DECLS + +#define XDG_TYPE_HOSTNAME_DAEMON (xdg_hostname_daemon_get_type ()) +#define XDG_HOSTNAME_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XDG_TYPE_HOSTNAME_DAEMON, XdgHostnameDaemon)) +#define XDG_HOSTNAME_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), XDG_TYPE_HOSTNAME_DAEMON, XdgHostnameDaemonClass)) +#define XDG_IS_HOSTNAME_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XDG_TYPE_HOSTNAME_DAEMON)) +#define XDG_IS_HOSTNAME_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), XDG_TYPE_HOSTNAME_DAEMON)) +#define XDG_HOSTNAME_DAEMON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), XDG_TYPE_HOSTNAME_DAEMON, XdgHostnameDaemonClass)) + +typedef struct _XdgHostnameDaemon XdgHostnameDaemon; +typedef struct _XdgHostnameDaemonClass XdgHostnameDaemonClass; + +GType xdg_hostname_daemon_get_type (void) G_GNUC_CONST; +XdgHostnameDaemon *xdg_hostname_daemon_new (DBusGConnection *connection, + const char *object_path); + +G_END_DECLS + +#endif /* __XDG_HOSTNAME_DAEMON_H__ */ diff --git a/src/programs/Makefile.am b/src/programs/Makefile.am new file mode 100644 index 0000000..c9337f4 --- /dev/null +++ b/src/programs/Makefile.am @@ -0,0 +1,38 @@ + +NULL = + +INCLUDES = \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_REENTRANT \ + $(NULL) + +bin_PROGRAMS = xdg-hostname-1 + +xdg_hostname_1_SOURCES = xdg-hostname.c + +xdg_hostname_1_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ + $(DBUS_GLIB_CFLAGS) \ + $(POLKIT_CFLAGS) \ + $(NULL) + +xdg_hostname_1_LDADD = \ + $(GLIB_LIBS) \ + $(GIO_LIBS) \ + $(DBUS_GLIB_LIBS) \ + $(POLKIT_LIBS) \ + $(top_builddir)/src/xdghostname/libxdg-hostname-gobject-1.la \ + $(NULL) + +clean-local: + rm -f *~ diff --git a/src/programs/xdg-hostname.c b/src/programs/xdg-hostname.c new file mode 100644 index 0000000..8401d66 --- /dev/null +++ b/src/programs/xdg-hostname.c @@ -0,0 +1,304 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include "config.h" +#include <sys/types.h> +#include <unistd.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <polkit-dbus/polkit-dbus.h> + +#include <xdghostname/xdghostname.h> + +static gboolean opt_show; +static gboolean opt_monitor; +static char *opt_set_display_hostname; +static char *opt_set_hostname; +static char *opt_set_icon_name; +static char *opt_set_use_transient_data; + +static GOptionEntry entries[] = { + { "show", 's', 0, G_OPTION_ARG_NONE, &opt_show, "Show hostname data", NULL }, + { "monitor", 'm', 0, G_OPTION_ARG_NONE, &opt_monitor, "Monitor hostname data for changes", NULL }, + { "set-display-hostname", 'd', 0, G_OPTION_ARG_STRING, &opt_set_display_hostname, "Set display hostname", NULL }, + { "set-hostname", 'h', 0, G_OPTION_ARG_STRING, &opt_set_hostname, "Set hostname", NULL }, + { "set-icon-name", 'i', 0, G_OPTION_ARG_STRING, &opt_set_icon_name, "Set icon", NULL }, + { "use-transient-data", 't', 0, G_OPTION_ARG_STRING, &opt_set_use_transient_data, "Set whether to use transient data", NULL }, + { NULL } +}; + +static gboolean +show_hostname_data (XdgHostnameMonitor *h) +{ + char *display_hostname; + char *hostname; + char *icon_name; + char *configured_display_hostname; + char *configured_hostname; + char *configured_icon_name; + gboolean use_transient_data; + char *transient_display_hostname; + char *transient_hostname; + char *transient_icon_name; + gboolean can_set_display_hostname; + gboolean can_set_hostname; + gboolean can_set_icon_name; + gboolean can_set_use_transient_data; + + g_object_get (h, + "display-hostname", &display_hostname, + "hostname", &hostname, + "icon-name", &icon_name, + "configured-display-hostname", &configured_display_hostname, + "configured-hostname", &configured_hostname, + "configured-icon-name", &configured_icon_name, + "use-transient-data", &use_transient_data, + "transient-display-hostname", &transient_display_hostname, + "transient-hostname", &transient_hostname, + "transient-icon-name", &transient_icon_name, + "can-set-display-hostname", &can_set_display_hostname, + "can-set-hostname", &can_set_hostname, + "can-set-icon-name", &can_set_icon_name, + "can-set-use-transient-data", &can_set_use_transient_data, + NULL); + + g_print ("display-hostname: %s\n", display_hostname); + g_print ("hostname: %s\n", hostname); + g_print ("icon_name: %s\n", icon_name); + g_print ("configured-hostname: %s\n", configured_hostname); + g_print ("configured-display_hostname: %s\n", configured_display_hostname); + g_print ("configured-icon_name: %s\n", configured_icon_name); + g_print ("use-transient-data: %s\n", use_transient_data ? "true" : "false"); + g_print ("transient-hostname: %s\n", transient_hostname); + g_print ("transient-display-hostname: %s\n", transient_display_hostname); + g_print ("transient-icon-name: %s\n", transient_icon_name); + g_print ("can-set-display-hostname: %s\n", can_set_display_hostname ? "true" : "false"); + g_print ("can-set-hostname: %s\n", can_set_hostname ? "true" : "false"); + g_print ("can-set-icon-name: %s\n", can_set_icon_name ? "true" : "false"); + g_print ("can-set-use-transient-data: %s\n", can_set_use_transient_data ? "true" : "false"); + + g_free (display_hostname); + g_free (hostname); + g_free (icon_name); + g_free (configured_display_hostname); + g_free (configured_hostname); + g_free (configured_icon_name); + g_free (transient_display_hostname); + g_free (transient_hostname); + g_free (transient_icon_name); + + return TRUE; +} + +static void +hostname_changed (XdgHostnameMonitor *h, + gpointer user_data) +{ + g_print ("Changed\n\n"); + show_hostname_data (h); +} + +static gboolean +monitor_hostname_data (XdgHostnameMonitor *h) +{ + GMainLoop *loop; + + g_print ("Monitoring hostname data for changes. Press Ctrl+C to exit.\n\n"); + + g_signal_connect (h, "changed", (GCallback) hostname_changed, NULL); + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + g_object_unref (loop); + + return TRUE; +} + +static gboolean +polkit_dbus_gerror_parse (GError *error, + PolKitAction **action, + PolKitResult *result) +{ + gboolean ret; + const char *name; + + ret = FALSE; + if (error->domain != DBUS_GERROR || error->code != DBUS_GERROR_REMOTE_EXCEPTION) + goto out; + + name = dbus_g_error_get_name (error); + + ret = polkit_dbus_error_parse_from_strings (name, + error->message, + action, + result); +out: + return ret; +} + +static gboolean +attempt_polkit (GError *error) +{ + gboolean ret; + PolKitAction *pk_action; + PolKitResult pk_result; + + ret = FALSE; + + if (polkit_dbus_gerror_parse (error, + &pk_action, + &pk_result)) { + char *action_id; + + if (polkit_action_get_action_id (pk_action, &action_id)) { + DBusError d_error; + + dbus_error_init (&d_error); + if (polkit_auth_obtain (action_id, + 0, + getpid (), + &d_error)) { + ret = TRUE; + } + if (dbus_error_is_set (&d_error)) { + dbus_error_free (&d_error); + } + } + + polkit_action_unref (pk_action); + } + + return ret; +} + +int +main (int argc, char *argv[]) +{ + GError *error; + GOptionContext *context; + XdgHostnameMonitor *hostname_monitor; + gboolean ret; + + ret = FALSE; + + g_type_init (); + + error = NULL; + context = g_option_context_new ("- manage hostname data"); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + g_option_context_parse (context, &argc, &argv, &error); + g_option_context_free (context); + + hostname_monitor = xdg_hostname_monitor_get (); + + if (opt_show) { + if (!show_hostname_data (hostname_monitor)) + goto out; + } + + if (opt_monitor) { + if (!monitor_hostname_data (hostname_monitor)) + goto out; + } + + if (opt_set_display_hostname != NULL) { + + retry_display_hostname: + if (!xdg_hostname_monitor_set_display_hostname_sync (hostname_monitor, + opt_set_display_hostname, + NULL, + &error)) { + if (attempt_polkit (error)) { + g_error_free (error); + goto retry_display_hostname; + } + g_printerr ("Error setting display-hostname: %s\n", error->message); + g_error_free (error); + goto out; + } + } + + if (opt_set_hostname != NULL) { + retry_hostname: + if (!xdg_hostname_monitor_set_hostname_sync (hostname_monitor, + opt_set_hostname, + NULL, + &error)) { + if (attempt_polkit (error)) { + g_error_free (error); + goto retry_hostname; + } + g_printerr ("Error setting hostname: %s\n", error->message); + g_error_free (error); + goto out; + } + } + + if (opt_set_icon_name != NULL) { + retry_icon_name: + if (!xdg_hostname_monitor_set_icon_name_sync (hostname_monitor, + opt_set_icon_name, + NULL, + &error)) { + if (attempt_polkit (error)) { + g_error_free (error); + goto retry_icon_name; + } + g_printerr ("Error setting icon-name: %s\n", error->message); + g_error_free (error); + goto out; + } + } + + if (opt_set_use_transient_data != NULL) { + gboolean val; + + val = FALSE; + if (g_ascii_strcasecmp (opt_set_use_transient_data, "1") == 0 || + g_ascii_strcasecmp (opt_set_use_transient_data, "true") == 0 || + g_ascii_strcasecmp (opt_set_use_transient_data, "yes") == 0) + val = TRUE; + + retry_use_transient_data: + if (!xdg_hostname_monitor_set_use_transient_data_sync (hostname_monitor, + val, + NULL, + &error)) { + if (attempt_polkit (error)) { + g_error_free (error); + goto retry_use_transient_data; + } + g_printerr ("Error setting use-transient-data: %s\n", error->message); + g_error_free (error); + goto out; + } + } + + ret = TRUE; + + out: + if (hostname_monitor != NULL) + g_object_unref (hostname_monitor); + + return ret ? 0 : 1; +} diff --git a/src/xdghostname/Makefile.am b/src/xdghostname/Makefile.am new file mode 100644 index 0000000..8a48988 --- /dev/null +++ b/src/xdghostname/Makefile.am @@ -0,0 +1,57 @@ +NULL = + +INCLUDES = \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_REENTRANT \ + -D_XDG_HOSTNAME_COMPILATION \ + $(NULL) + +BUILT_SOURCES = \ + xdghostnameclientglue.h \ + $(NULL) + +xdghostnameclientglue.h: $(top_srcdir)/data/org.freedesktop.Hostname1.xml Makefile.am + dbus-binding-tool --mode=glib-client --output=xdghostnameclientglue.h $(top_srcdir)/data/org.freedesktop.Hostname1.xml + +lib_LTLIBRARIES=libxdg-hostname-gobject-1.la + +libxdg_hostname_gobject_1includedir=$(includedir)/xdghostname-1/xdghostname + +libxdg_hostname_gobject_1include_HEADERS = \ + xdghostname.h \ + xdghostnameerror.h \ + xdghostnamemonitor.h \ + $(NULL) + +libxdg_hostname_gobject_1_la_SOURCES = \ + xdghostname.h \ + xdghostnameerror.h xdghostnameerror.c \ + xdghostnamemonitor.h xdghostnamemonitor.c \ + $(BUILT_SOURCES) \ + $(NULL) + +libxdg_hostname_gobject_1_la_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ + $(DBUS_GLIB_CFLAGS) \ + $(NULL) + +libxdg_hostname_gobject_1_la_LIBADD = \ + $(GLIB_LIBS) \ + $(GIO_LIBS) \ + $(DBUS_GLIB_LIBS) \ + $(NULL) + +CLEANFILES = $(BUILT_SOURCES) + +clean-local : + rm -f *~ diff --git a/src/xdghostname/xdghostname.h b/src/xdghostname/xdghostname.h new file mode 100644 index 0000000..6584b9d --- /dev/null +++ b/src/xdghostname/xdghostname.h @@ -0,0 +1,33 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifndef __XDG_HOSTNAME_H +#define __XDG_HOSTNAME_H + +#define _XDG_HOSTNAME_INSIDE_XDG_HOSTNAME_H 1 +#include <xdghostname/xdghostnameerror.h> +#include <xdghostname/xdghostnamemonitor.h> +#undef _XDG_HOSTNAME_INSIDE_XDG_HOSTNAME_H + +#endif /* __XDG_HOSTNAME_H */ + diff --git a/src/xdghostname/xdghostnameerror.c b/src/xdghostname/xdghostnameerror.c new file mode 100644 index 0000000..fcdf7c0 --- /dev/null +++ b/src/xdghostname/xdghostnameerror.c @@ -0,0 +1,70 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include "config.h" +#include <string.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include "xdghostnameerror.h" + +/** + * SECTION:xdghostnameerror + * @title: XdgHostnameError + * @short_description: Error domain for xdg-hostname + * @include: xdghostname/xdghostname.h + * + * Error domain for xdg-hostname + */ + +/** + * xdg_hostname_error_quark: + * + * Gets the #XdgHostnameError Quark. + * + * Return value: a #GQuark. + **/ +GQuark +xdg_hostname_error_quark (void) +{ + return g_quark_from_static_string ("xdg-hostname-error-quark"); +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +xdg_hostname_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (XDG_HOSTNAME_ERROR_FAILED, "Failed"), + ENUM_ENTRY (XDG_HOSTNAME_ERROR_NOT_SUPPORTED, "NotSupported"), + { 0, 0, 0 } + }; + g_assert (XDG_HOSTNAME_ERROR_NUM_ERRORS == G_N_ELEMENTS (values) - 1); + etype = g_enum_register_static ("XdgHostnameErrorEnum", values); + } + return etype; +} diff --git a/src/xdghostname/xdghostnameerror.h b/src/xdghostname/xdghostnameerror.h new file mode 100644 index 0000000..4139570 --- /dev/null +++ b/src/xdghostname/xdghostnameerror.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#if !defined (_XDG_HOSTNAME_COMPILATION) && !defined(_XDG_HOSTNAME_INSIDE_XDG_HOSTNAME_H) +#error "Only <xdghostname/xdghostname.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef __XDG_HOSTNAME_ERROR_H +#define __XDG_HOSTNAME_ERROR_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define XDG_HOSTNAME_TYPE_ERROR (xdg_hostname_error_get_type ()) + +/** + * XDG_HOSTNAME_ERROR: + * + * Error domain for xdg-hostname. Errors in this domain will be from the + * #XdgHostnameErrorEnum enumeration. See #GError for more information on + * error domains. + **/ +#define XDG_HOSTNAME_ERROR xdg_hostname_error_quark() + +GQuark xdg_hostname_error_quark (void); +GType xdg_hostname_error_get_type (void) G_GNUC_CONST; + +/** + * XdgHostnameErrorEnum: + * @XDG_HOSTNAME_ERROR_FAILED: The operation failed. + * @XDG_HOSTNAME_ERROR_NOT_SUPPORTED: Operation not supported. + * + * Error codes returned by PolicyKit functions. + */ +typedef enum { + XDG_HOSTNAME_ERROR_FAILED, + XDG_HOSTNAME_ERROR_NOT_SUPPORTED, + XDG_HOSTNAME_ERROR_NUM_ERRORS +} XdgHostnameErrorEnum; + +G_END_DECLS + +#endif /* __XDG_HOSTNAME_ERROR_H */ + diff --git a/src/xdghostname/xdghostnamemonitor.c b/src/xdghostname/xdghostnamemonitor.c new file mode 100644 index 0000000..5e43fdd --- /dev/null +++ b/src/xdghostname/xdghostnamemonitor.c @@ -0,0 +1,741 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#include "config.h" +#include <string.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include "xdghostnamemonitor.h" + +#include "xdghostnameclientglue.h" + +/** + * SECTION:xdghostnamemonitor + * @title: XdgHostnameMonitor + * @short_description: Read, monitor and change hostname data + * @include: xdghostname/xdghostname.h + * + * The #XdgHostnameMonitor class is used for managing hostname data. + */ + +struct _XdgHostnameMonitor +{ + GObject parent_instance; + + char *display_hostname; + char *hostname; + char *icon_name; + + char *configured_display_hostname; + char *configured_hostname; + char *configured_icon_name; + + gboolean use_transient_data; + + char *transient_display_hostname; + char *transient_hostname; + char *transient_icon_name; + + gboolean can_set_display_hostname; + gboolean can_set_hostname; + gboolean can_set_icon_name; + gboolean can_set_use_transient_data; + + DBusGProxy *proxy; + DBusGProxy *prop_proxy; +}; + +struct _XdgHostnameMonitorClass +{ + GObjectClass parent_class; + + void (* changed) (XdgHostnameMonitor *hostname_monitor); +}; + +enum { + PROP_0, + + PROP_DISPLAY_HOSTNAME, + PROP_HOSTNAME, + PROP_ICON_NAME, + + PROP_CONFIGURED_DISPLAY_HOSTNAME, + PROP_CONFIGURED_HOSTNAME, + PROP_CONFIGURED_ICON_NAME, + PROP_USE_TRANSIENT_DATA, + + PROP_TRANSIENT_DISPLAY_HOSTNAME, + PROP_TRANSIENT_HOSTNAME, + PROP_TRANSIENT_ICON_NAME, + + PROP_CAN_SET_DISPLAY_HOSTNAME, + PROP_CAN_SET_HOSTNAME, + PROP_CAN_SET_ICON_NAME, + PROP_CAN_SET_USE_TRANSIENT_DATA, +}; + +enum { + CHANGED_SIGNAL, + LAST_SIGNAL, +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (XdgHostnameMonitor, xdg_hostname_monitor, G_TYPE_OBJECT); + +static void +xdg_hostname_monitor_finalize (GObject *object) +{ + XdgHostnameMonitor *hostname_monitor; + + hostname_monitor = XDG_HOSTNAME_MONITOR (object); + + if (hostname_monitor->proxy != NULL) + g_object_unref (hostname_monitor->proxy); + if (hostname_monitor->prop_proxy != NULL) + g_object_unref (hostname_monitor->prop_proxy); + + g_free (hostname_monitor->display_hostname); + g_free (hostname_monitor->hostname); + g_free (hostname_monitor->icon_name); + + g_free (hostname_monitor->configured_display_hostname); + g_free (hostname_monitor->configured_hostname); + g_free (hostname_monitor->configured_icon_name); + + g_free (hostname_monitor->transient_display_hostname); + g_free (hostname_monitor->transient_hostname); + g_free (hostname_monitor->transient_icon_name); + + G_OBJECT_CLASS (xdg_hostname_monitor_parent_class)->finalize (object); +} + + +static void +xdg_hostname_monitor_init (XdgHostnameMonitor *hostname_monitor) +{ +} + +static void +xdg_hostname_monitor_constructed (GObject *object) +{ + XdgHostnameMonitor *hostname_monitor; + + hostname_monitor = XDG_HOSTNAME_MONITOR (object); + + if (G_OBJECT_CLASS (xdg_hostname_monitor_parent_class)->constructed != NULL) + G_OBJECT_CLASS (xdg_hostname_monitor_parent_class)->constructed (object); +} + +static void +xdg_hostname_monitor_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + XdgHostnameMonitor *hostname_monitor; + + g_return_if_fail (XDG_IS_HOSTNAME_MONITOR (object)); + + hostname_monitor = XDG_HOSTNAME_MONITOR (object); + + switch (prop_id) { + case PROP_DISPLAY_HOSTNAME: + g_value_set_string (value, hostname_monitor->display_hostname); + break; + + case PROP_HOSTNAME: + g_value_set_string (value, hostname_monitor->hostname); + break; + + case PROP_ICON_NAME: + g_value_set_string (value, hostname_monitor->icon_name); + break; + + case PROP_CONFIGURED_DISPLAY_HOSTNAME: + g_value_set_string (value, hostname_monitor->configured_display_hostname); + break; + + case PROP_CONFIGURED_HOSTNAME: + g_value_set_string (value, hostname_monitor->configured_hostname); + break; + + case PROP_CONFIGURED_ICON_NAME: + g_value_set_string (value, hostname_monitor->configured_icon_name); + break; + + case PROP_USE_TRANSIENT_DATA: + g_value_set_boolean (value, hostname_monitor->use_transient_data); + break; + + case PROP_TRANSIENT_DISPLAY_HOSTNAME: + g_value_set_string (value, hostname_monitor->transient_display_hostname); + break; + + case PROP_TRANSIENT_HOSTNAME: + g_value_set_string (value, hostname_monitor->transient_hostname); + break; + + case PROP_TRANSIENT_ICON_NAME: + g_value_set_string (value, hostname_monitor->transient_icon_name); + break; + + case PROP_CAN_SET_DISPLAY_HOSTNAME: + g_value_set_boolean (value, hostname_monitor->can_set_display_hostname); + break; + + case PROP_CAN_SET_HOSTNAME: + g_value_set_boolean (value, hostname_monitor->can_set_hostname); + break; + + case PROP_CAN_SET_ICON_NAME: + g_value_set_boolean (value, hostname_monitor->can_set_icon_name); + break; + + case PROP_CAN_SET_USE_TRANSIENT_DATA: + g_value_set_boolean (value, hostname_monitor->can_set_use_transient_data); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +xdg_hostname_monitor_class_init (XdgHostnameMonitorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = xdg_hostname_monitor_finalize; + gobject_class->constructed = xdg_hostname_monitor_constructed; + gobject_class->get_property = xdg_hostname_monitor_get_property; + + /** + * XdgHostnameMonitor::changed: + * @hostname_monitor: a #XdgHostnameMonitor. + * + * Emitted when something on @hostname_monitor changes. + */ + signals[CHANGED_SIGNAL] = g_signal_new ("changed", + XDG_TYPE_HOSTNAME_MONITOR, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (XdgHostnameMonitorClass, changed), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_object_class_install_property (gobject_class, + PROP_DISPLAY_HOSTNAME, + g_param_spec_string ("display-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_HOSTNAME, + g_param_spec_string ("hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_ICON_NAME, + g_param_spec_string ("icon-name", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_CONFIGURED_DISPLAY_HOSTNAME, + g_param_spec_string ("configured-display-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_CONFIGURED_HOSTNAME, + g_param_spec_string ("configured-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_CONFIGURED_ICON_NAME, + g_param_spec_string ("configured-icon-name", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_USE_TRANSIENT_DATA, + g_param_spec_boolean ("use-transient-data", + NULL, + NULL, + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_TRANSIENT_DISPLAY_HOSTNAME, + g_param_spec_string ("transient-display-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_TRANSIENT_HOSTNAME, + g_param_spec_string ("transient-hostname", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_TRANSIENT_ICON_NAME, + g_param_spec_string ("transient-icon-name", + NULL, + NULL, + NULL, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_CAN_SET_DISPLAY_HOSTNAME, + g_param_spec_boolean ("can-set-display-hostname", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_CAN_SET_HOSTNAME, + g_param_spec_boolean ("can-set-hostname", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_CAN_SET_ICON_NAME, + g_param_spec_boolean ("can-set-icon-name", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_CAN_SET_USE_TRANSIENT_DATA, + g_param_spec_boolean ("can-set-use-transient-data", + NULL, + NULL, + TRUE, + G_PARAM_READABLE)); + +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static int +safe_strcmp (const char *a, const char *b) +{ + if (a == NULL) + a = ""; + if (b == NULL) + b = ""; + + return strcmp (a, b); +} + +static gboolean glob_changed; + +#define SET_STRING(member, propname) do {gboolean c = safe_strcmp (h-> member, g_value_get_string (value)) == 0; g_free (h-> member); h-> member = g_strdup (g_value_get_string (value)); if (c) {g_object_notify (G_OBJECT (h), propname); glob_changed = TRUE;}} while (FALSE); + +#define SET_BOOL(member, propname) do {gboolean c = (h-> member != g_value_get_boolean (value)); h-> member = g_value_get_boolean (value); if (c) {g_object_notify (G_OBJECT (h), propname); glob_changed = TRUE;}} while (FALSE); + +static void +collect_props (const char *key, const GValue *value, XdgHostnameMonitor *h) +{ + gboolean handled; + + handled = TRUE; + + if (strcmp (key, "display-hostname") == 0) { + SET_STRING (display_hostname, "display-hostname"); + + } else if (strcmp (key, "hostname") == 0) { + SET_STRING (hostname, "hostname"); + + } else if (strcmp (key, "icon-name") == 0) { + SET_STRING (icon_name, "icon-name"); + + } else if (strcmp (key, "configured-display-hostname") == 0) { + SET_STRING (configured_display_hostname, "configured-display-hostname"); + + } else if (strcmp (key, "configured-hostname") == 0) { + SET_STRING (configured_hostname, "configured-hostname"); + + } else if (strcmp (key, "configured-icon-name") == 0) { + SET_STRING (configured_icon_name, "configured-icon-name"); + + } else if (strcmp (key, "use-transient-data") == 0) { + SET_BOOL (use_transient_data, "use-transient-data"); + + } else if (strcmp (key, "transient-display-hostname") == 0) { + SET_STRING (transient_display_hostname, "transient-display-hostname"); + + } else if (strcmp (key, "transient-hostname") == 0) { + SET_STRING (transient_hostname, "transient-hostname"); + + } else if (strcmp (key, "transient-icon-name") == 0) { + SET_STRING (transient_icon_name, "transient-icon-name"); + + } else if (strcmp (key, "can-set-display-hostname") == 0) { + SET_BOOL (can_set_display_hostname, "can-set-display-hostname"); + + } else if (strcmp (key, "can-set-hostname") == 0) { + SET_BOOL (can_set_hostname, "can-set-hostname"); + + } else if (strcmp (key, "can-set-icon-name") == 0) { + SET_BOOL (can_set_icon_name, "can-set-icon-name"); + + } else if (strcmp (key, "can-set-use-transient-data") == 0) { + SET_BOOL (can_set_use_transient_data, "can-set-use-transient-data"); + + } else { + handled = FALSE; + } + + if (!handled) + g_warning ("unhandled property '%s'", key); +} + +static void +update_props (XdgHostnameMonitor *hostname_monitor) +{ + GError *error; + GHashTable *hash_table; + + error = NULL; + if (!dbus_g_proxy_call (hostname_monitor->prop_proxy, + "GetAll", + &error, + G_TYPE_STRING, + "org.freedesktop.Hostname1", + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &hash_table, + G_TYPE_INVALID)) { + g_warning ("Couldn't call GetAll() to get properties: %s", error->message); + g_error_free (error); + goto out; + } + + g_hash_table_foreach (hash_table, (GHFunc) collect_props, hostname_monitor); + + if (glob_changed) + g_signal_emit (hostname_monitor, signals[CHANGED_SIGNAL], 0); + + g_hash_table_unref (hash_table); + out: + ; +} + +static void +hostname_monitor_changed_cb (DBusGProxy *proxy, + XdgHostnameMonitor *hostname_monitor) +{ + update_props (hostname_monitor); +} + +static XdgHostnameMonitor * +_xdg_hostname_monitor_new (DBusGConnection *connection, + const char *service_name, + const char *object_path) +{ + XdgHostnameMonitor *hostname_monitor; + + hostname_monitor = XDG_HOSTNAME_MONITOR (g_object_new (XDG_TYPE_HOSTNAME_MONITOR, NULL)); + + hostname_monitor->proxy = dbus_g_proxy_new_for_name (connection, + service_name, + object_path, + "org.freedesktop.Hostname1"); + + hostname_monitor->prop_proxy = dbus_g_proxy_new_for_name (connection, + service_name, + object_path, + "org.freedesktop.DBus.Properties"); + + dbus_g_proxy_add_signal (hostname_monitor->proxy, + "Changed", + G_TYPE_INVALID); + + dbus_g_proxy_connect_signal (hostname_monitor->proxy, "Changed", + (GCallback) hostname_monitor_changed_cb, + hostname_monitor, + NULL); + + update_props (hostname_monitor); + + return hostname_monitor; +} + +/** + * xdg_hostname_monitor_get: + * + * Gets the default hostname monitor. + * + * Returns: A reference to a #XdgHostnameMonitor instance. Call + * g_object_unref() when you are done with it. + **/ +XdgHostnameMonitor * +xdg_hostname_monitor_get (void) +{ + XdgHostnameMonitor *hostname_monitor; + DBusGConnection *bus; + GError *error; + + bus = NULL; + hostname_monitor = NULL; + + error = NULL; + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (bus == NULL) { + g_warning ("Couldn't connect to system bus: %s", error->message); + g_error_free (error); + goto out; + } + + hostname_monitor = _xdg_hostname_monitor_new (bus, + "org.freedesktop.Hostname1", + "/org/freedesktop/hostname1"); + + out: + if (bus != NULL) + dbus_g_connection_unref (bus); + return hostname_monitor; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +generic_async_cb (DBusGProxy *proxy, + GError *error, + gpointer user_data) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + if (error != NULL) + g_simple_async_result_set_from_error (simple, error); + else + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +gboolean +xdg_hostname_monitor_set_display_hostname_sync (XdgHostnameMonitor *hostname_monitor, + const gchar *display_hostname, + GCancellable *cancellable, + GError **error) +{ + return org_freedesktop_Hostname1_set_display_hostname (hostname_monitor->proxy, + display_hostname, + error); +} + +void +xdg_hostname_monitor_set_display_hostname (XdgHostnameMonitor *hostname_monitor, + const gchar *display_hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (G_OBJECT (hostname_monitor), + callback, + user_data, + xdg_hostname_monitor_set_display_hostname); + + org_freedesktop_Hostname1_set_display_hostname_async (hostname_monitor->proxy, + display_hostname, + generic_async_cb, + simple); +} + +gboolean +xdg_hostname_monitor_set_display_hostname_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == xdg_hostname_monitor_set_display_hostname); + g_simple_async_result_propagate_error (simple, error); + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +gboolean +xdg_hostname_monitor_set_hostname_sync (XdgHostnameMonitor *hostname_monitor, + const gchar *hostname, + GCancellable *cancellable, + GError **error) +{ + return org_freedesktop_Hostname1_set_hostname (hostname_monitor->proxy, + hostname, + error); +} + +void +xdg_hostname_monitor_set_hostname (XdgHostnameMonitor *hostname_monitor, + const gchar *hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (G_OBJECT (hostname_monitor), + callback, + user_data, + xdg_hostname_monitor_set_hostname); + + org_freedesktop_Hostname1_set_hostname_async (hostname_monitor->proxy, + hostname, + generic_async_cb, + simple); +} + +gboolean +xdg_hostname_monitor_set_hostname_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == xdg_hostname_monitor_set_hostname); + g_simple_async_result_propagate_error (simple, error); + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +gboolean +xdg_hostname_monitor_set_icon_name_sync (XdgHostnameMonitor *hostname_monitor, + const gchar *icon_name, + GCancellable *cancellable, + GError **error) +{ + return org_freedesktop_Hostname1_set_icon_name (hostname_monitor->proxy, + icon_name, + error); +} + +void +xdg_hostname_monitor_set_icon_name (XdgHostnameMonitor *hostname_monitor, + const gchar *icon_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (G_OBJECT (hostname_monitor), + callback, + user_data, + xdg_hostname_monitor_set_icon_name); + + org_freedesktop_Hostname1_set_icon_name_async (hostname_monitor->proxy, + icon_name, + generic_async_cb, + simple); +} + +gboolean +xdg_hostname_monitor_set_icon_name_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == xdg_hostname_monitor_set_icon_name); + g_simple_async_result_propagate_error (simple, error); + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +gboolean +xdg_hostname_monitor_set_use_transient_data_sync (XdgHostnameMonitor *hostname_monitor, + gboolean use_transient_data, + GCancellable *cancellable, + GError **error) +{ + return org_freedesktop_Hostname1_set_use_transient_data (hostname_monitor->proxy, + use_transient_data, + error); +} + + +void +xdg_hostname_monitor_set_use_transient_data (XdgHostnameMonitor *hostname_monitor, + gboolean use_transient_data, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (G_OBJECT (hostname_monitor), + callback, + user_data, + xdg_hostname_monitor_set_use_transient_data); + + org_freedesktop_Hostname1_set_use_transient_data_async (hostname_monitor->proxy, + use_transient_data, + generic_async_cb, + simple); +} + +gboolean +xdg_hostname_monitor_set_use_transient_data_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == xdg_hostname_monitor_set_use_transient_data); + g_simple_async_result_propagate_error (simple, error); + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/xdghostname/xdghostnamemonitor.h b/src/xdghostname/xdghostnamemonitor.h new file mode 100644 index 0000000..ea7ca7d --- /dev/null +++ b/src/xdghostname/xdghostnamemonitor.h @@ -0,0 +1,116 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ + +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#if !defined (_XDG_HOSTNAME_COMPILATION) && !defined(_XDG_HOSTNAME_INSIDE_XDG_HOSTNAME_H) +#error "Only <xdghostname/xdghostname.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef __XDG_HOSTNAME_MONITOR_H +#define __XDG_HOSTNAME_MONITOR_H + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define XDG_TYPE_HOSTNAME_MONITOR (xdg_hostname_monitor_get_type ()) +#define XDG_HOSTNAME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XDG_TYPE_HOSTNAME_MONITOR, XdgHostnameMonitor)) +#define XDG_HOSTNAME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), XDG_TYPE_HOSTNAME_MONITOR, XdgHostnameMonitorClass)) +#define XDG_HOSTNAME_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), XDG_TYPE_HOSTNAME_MONITOR, XdgHostnameMonitorClass)) +#define XDG_IS_HOSTNAME_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XDG_TYPE_HOSTNAME_MONITOR)) +#define XDG_IS_HOSTNAME_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), XDG_TYPE_HOSTNAME_MONITOR)) + +typedef struct _XdgHostnameMonitor XdgHostnameMonitor; +typedef struct _XdgHostnameMonitorClass XdgHostnameMonitorClass; + +GType xdg_hostname_monitor_get_type (void) G_GNUC_CONST; + +void xdg_hostname_monitor_set_display_hostname (XdgHostnameMonitor *hostname_monitor, + const gchar *display_hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean xdg_hostname_monitor_set_display_hostname_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error); + +gboolean xdg_hostname_monitor_set_display_hostname_sync (XdgHostnameMonitor *hostname_monitor, + const gchar *display_hostname, + GCancellable *cancellable, + GError **error); + + +void xdg_hostname_monitor_set_hostname (XdgHostnameMonitor *hostname_monitor, + const gchar *hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean xdg_hostname_monitor_set_hostname_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error); + +gboolean xdg_hostname_monitor_set_hostname_sync (XdgHostnameMonitor *hostname_monitor, + const gchar *hostname, + GCancellable *cancellable, + GError **error); + + +void xdg_hostname_monitor_set_icon_name (XdgHostnameMonitor *hostname_monitor, + const gchar *icon_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean xdg_hostname_monitor_set_icon_name_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error); + +gboolean xdg_hostname_monitor_set_icon_name_sync (XdgHostnameMonitor *hostname_monitor, + const gchar *icon_name, + GCancellable *cancellable, + GError **error); + + +void xdg_hostname_monitor_set_use_transient_data (XdgHostnameMonitor *hostname_monitor, + gboolean use_transient_data, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean xdg_hostname_monitor_set_use_transient_data_finish (XdgHostnameMonitor *hostname_monitor, + GAsyncResult *res, + GError **error); + +gboolean xdg_hostname_monitor_set_use_transient_data_sync (XdgHostnameMonitor *hostname_monitor, + gboolean use_transient_data, + GCancellable *cancellable, + GError **error); + +XdgHostnameMonitor *xdg_hostname_monitor_get (void); + +G_END_DECLS + +#endif /* __XDG_HOSTNAME_MONITOR_H */ + |