diff options
Diffstat (limited to 'apps/xrdb')
-rw-r--r-- | apps/xrdb/.gitignore | 79 | ||||
-rw-r--r-- | apps/xrdb/AUTHORS | 3 | ||||
-rw-r--r-- | apps/xrdb/COPYING | 51 | ||||
-rw-r--r-- | apps/xrdb/Makefile.am | 43 | ||||
-rw-r--r-- | apps/xrdb/README | 25 | ||||
-rwxr-xr-x | apps/xrdb/autogen.sh | 13 | ||||
-rw-r--r-- | apps/xrdb/configure.ac | 91 | ||||
-rw-r--r-- | apps/xrdb/man/Makefile.am | 12 | ||||
-rw-r--r-- | apps/xrdb/man/xrdb.man | 302 | ||||
-rw-r--r-- | apps/xrdb/xrdb.c | 1408 |
10 files changed, 2027 insertions, 0 deletions
diff --git a/apps/xrdb/.gitignore b/apps/xrdb/.gitignore new file mode 100644 index 000000000..0d6e60997 --- /dev/null +++ b/apps/xrdb/.gitignore @@ -0,0 +1,79 @@ +# +# X.Org module default exclusion patterns +# The next section if for module specific patterns +# +# Do not edit the following section +# GNU Build System (Autotools) +aclocal.m4 +autom4te.cache/ +autoscan.log +ChangeLog +compile +config.guess +config.h +config.h.in +config.log +config-ml.in +config.py +config.status +config.status.lineno +config.sub +configure +configure.scan +depcomp +.deps/ +INSTALL +install-sh +.libs/ +libtool +libtool.m4 +ltmain.sh +lt~obsolete.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +Makefile +Makefile.in +mdate-sh +missing +mkinstalldirs +*.pc +py-compile +stamp-h? +symlink-tree +texinfo.tex +ylwrap + +# Do not edit the following section +# Edit Compile Debug Document Distribute +*~ +*.[0-9] +*.[0-9]x +*.bak +*.bin +core +*.dll +*.exe +*-ISO*.bdf +*-JIS*.bdf +*-KOI8*.bdf +*.kld +*.ko +*.ko.cmd +*.lai +*.l[oa] +*.[oa] +*.obj +*.patch +*.so +*.pcf.gz +*.pdb +*.tar.bz2 +*.tar.gz +# +# Add & Override patterns for xrdb +# +# Edit the following section as needed +# For example, !report.pc overrides *.pc. See 'man gitignore' +# +xrdb diff --git a/apps/xrdb/AUTHORS b/apps/xrdb/AUTHORS new file mode 100644 index 000000000..09c906f4f --- /dev/null +++ b/apps/xrdb/AUTHORS @@ -0,0 +1,3 @@ + * Original Author: Jim Gettys, August 28, 1987 + * Extensively Modified: Phil Karlton, January 5, 1987 + * Modified a Bunch More: Bob Scheifler, February, 1991 diff --git a/apps/xrdb/COPYING b/apps/xrdb/COPYING new file mode 100644 index 000000000..9783f04f7 --- /dev/null +++ b/apps/xrdb/COPYING @@ -0,0 +1,51 @@ + + COPYRIGHT 1987, 1991 + DIGITAL EQUIPMENT CORPORATION + MAYNARD, MASSACHUSETTS + MASSACHUSETTS INSTITUTE OF TECHNOLOGY + CAMBRIDGE, MASSACHUSETTS + ALL RIGHTS RESERVED. + +THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND +SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. +DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR +ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. + +IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, +APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT +SET FORTH ABOVE. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the name of Digital Equipment Corporation not be +used in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. + + ---------------------------------------------------------------- + +Copyright 1991, Digital Equipment Corporation. +Copyright 1991, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +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 OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. diff --git a/apps/xrdb/Makefile.am b/apps/xrdb/Makefile.am new file mode 100644 index 000000000..251261b3f --- /dev/null +++ b/apps/xrdb/Makefile.am @@ -0,0 +1,43 @@ +# +# Copyright 2005 Red Hat, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +SUBDIRS = man +bin_PROGRAMS = xrdb + +AM_CFLAGS = $(CWARNFLAGS) $(XRDB_CFLAGS) +xrdb_LDADD = $(XRDB_LIBS) + +xrdb_SOURCES = \ + xrdb.c + +MAINTAINERCLEANFILES = ChangeLog INSTALL + +.PHONY: ChangeLog INSTALL + +INSTALL: + $(INSTALL_CMD) + +ChangeLog: + $(CHANGELOG_CMD) + +dist-hook: ChangeLog INSTALL + + diff --git a/apps/xrdb/README b/apps/xrdb/README new file mode 100644 index 000000000..48a9ed864 --- /dev/null +++ b/apps/xrdb/README @@ -0,0 +1,25 @@ +xrdb - X server resource database utility + +All questions regarding this software should be directed at the +Xorg mailing list: + + http://lists.freedesktop.org/mailman/listinfo/xorg + +Please submit bug reports to the Xorg bugzilla: + + https://bugs.freedesktop.org/enter_bug.cgi?product=xorg + +The master development code repository can be found at: + + git://anongit.freedesktop.org/git/xorg/app/xrdb + + http://cgit.freedesktop.org/xorg/app/xrdb + +For patch submission instructions, see: + + http://www.x.org/wiki/Development/Documentation/SubmittingPatches + +For more information on the git code manager, see: + + http://wiki.x.org/wiki/GitPage + diff --git a/apps/xrdb/autogen.sh b/apps/xrdb/autogen.sh new file mode 100755 index 000000000..e81f98910 --- /dev/null +++ b/apps/xrdb/autogen.sh @@ -0,0 +1,13 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure --enable-maintainer-mode "$@" + diff --git a/apps/xrdb/configure.ac b/apps/xrdb/configure.ac new file mode 100644 index 000000000..04aa03400 --- /dev/null +++ b/apps/xrdb/configure.ac @@ -0,0 +1,91 @@ +dnl Copyright 2005 Red Hat, Inc. +dnl +dnl Permission to use, copy, modify, distribute, and sell this software and its +dnl documentation for any purpose is hereby granted without fee, provided that +dnl the above copyright notice appear in all copies and that both that +dnl copyright notice and this permission notice appear in supporting +dnl documentation, and that the name of Red Hat not be used in +dnl advertising or publicity pertaining to distribution of the software without +dnl specific, written prior permission. Red Hat makes no +dnl representations about the suitability of this software for any purpose. It +dnl is provided "as is" without express or implied warranty. +dnl +dnl RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +dnl INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +dnl EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +dnl CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +dnl DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +dnl TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +dnl PERFORMANCE OF THIS SOFTWARE. +dnl +dnl Process this file with autoconf to create configure. + +# Initialize Autoconf +AC_PREREQ([2.60]) +AC_INIT([xrdb], [1.0.9], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xrdb]) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS([config.h]) +AC_USE_SYSTEM_EXTENSIONS + +# Initialize Automake +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_MAINTAINER_MODE + +# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.8) +XORG_DEFAULT_OPTIONS + +AC_CHECK_FUNCS([mkstemp asprintf]) + +# Find MAXHOSTNAMELEN definition +# Common hidey holes: +# BSD & Linux - <sys/param.h> +# Solaris - <netdb.h> + +AC_CHECK_DECL([MAXHOSTNAMELEN],[FOUND_MAXHOSTNAMELEN=yes]) + +if test x$FOUND_MAXHOSTNAMELEN != xyes ; then + AC_MSG_CHECKING([for header that defines MAXHOSTNAMELEN]) + + FOUND_MAXHOSTNAMELEN='not found' + + AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([#include <sys/param.h>], + [int h = MAXHOSTNAMELEN;]), + [FOUND_MAXHOSTNAMELEN='sys/param.h' + AC_DEFINE(NEED_SYS_PARAM_H,1, + [Define to 1 if you need <sys/param.h> to define MAXHOSTNAMELEN])]) + + AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([#include <netdb.h>], + [int h = MAXHOSTNAMELEN;]), + [FOUND_MAXHOSTNAMELEN='netdb.h' + AC_DEFINE(NEED_NETDB_H,1, + [Define to 1 if you need <netdb.h> to define MAXHOSTNAMELEN])]) + + AC_MSG_RESULT([$FOUND_MAXHOSTNAMELEN]) +fi + +# xrdb needs to know where to find cpp at runtime - previously set as CppCmd +# in Imake config files for each OS +AC_ARG_WITH([cpp], + AS_HELP_STRING([--with-cpp=path], + [comma-separated list of paths to cpp command for xrdb to use at runtime]), + [AC_MSG_CHECKING(for cpp) + CPP_PATH=$withval + AC_MSG_RESULT(--with-cpp specified $CPP_PATH)], + [AC_PATH_PROG([CPP_PATH],[cpp], [cpp], + [$PATH:/bin:/usr/bin:/usr/lib:/usr/libexec:/usr/ccs/lib:/usr/ccs/lbin:/lib])]) +CPP_PATH=`echo ${CPP_PATH} | sed 's/,/\\",\\"/g'` +AC_DEFINE_UNQUOTED([CPP], "$CPP_PATH", [Path to CPP program]) + +# Checks for pkg-config packages +PKG_CHECK_MODULES(XRDB, xmuu x11) + +AC_CONFIG_FILES([ + Makefile + man/Makefile]) +AC_OUTPUT diff --git a/apps/xrdb/man/Makefile.am b/apps/xrdb/man/Makefile.am new file mode 100644 index 000000000..95a4ed588 --- /dev/null +++ b/apps/xrdb/man/Makefile.am @@ -0,0 +1,12 @@ + +appmandir = $(APP_MAN_DIR) +appman_PRE = xrdb.man +appman_DATA = $(appman_PRE:man=$(APP_MAN_SUFFIX)) + +EXTRA_DIST = $(appman_PRE) +CLEANFILES = $(appman_DATA) +SUFFIXES = .$(APP_MAN_SUFFIX) .man + +# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure +.man.$(APP_MAN_SUFFIX): + $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@ diff --git a/apps/xrdb/man/xrdb.man b/apps/xrdb/man/xrdb.man new file mode 100644 index 000000000..e30b0d553 --- /dev/null +++ b/apps/xrdb/man/xrdb.man @@ -0,0 +1,302 @@ +.\" Copyright 1991, Digital Equipment Corporation. +.\" Copyright 1991, 1994, 1998 The Open Group +.\" +.\" Permission to use, copy, modify, distribute, and sell this software and its +.\" documentation for any purpose is hereby granted without fee, provided that +.\" the above copyright notice appear in all copies and that both that +.\" copyright notice and this permission notice appear in supporting +.\" documentation. +.\" +.\" 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 OPEN GROUP 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. +.\" +.\" Except as contained in this notice, the name of The Open Group shall +.\" not be used in advertising or otherwise to promote the sale, use or +.\" other dealings in this Software without prior written authorization +.\" from The Open Group. +.\" +.TH XRDB 1 __xorgversion__ +.SH NAME +xrdb - X server resource database utility +.SH SYNOPSIS +.B xrdb +[-option ...] [\fIfilename\fP] +.SH DESCRIPTION +.I Xrdb +is used to get or set the contents of the RESOURCE_MANAGER property +on the root window of screen 0, or the SCREEN_RESOURCES property on +the root window of any or all screens, or everything combined. +You would normally run this program from your X startup file. +.LP +Most X clients use the RESOURCE_MANAGER and SCREEN_RESOURCES properties to +get user preferences about +color, fonts, and so on for applications. Having this information in +the server (where it is available to all clients) instead of on disk, +solves the problem in previous versions of X that required you to +maintain \fIdefaults\fP files on every machine that you might use. +It also allows for dynamic changing of defaults without editing files. +.LP +The RESOURCE_MANAGER property is used for resources that apply to all +screens of the display. The SCREEN_RESOURCES property on each screen +specifies additional (or overriding) resources to be used for that screen. +(When there is only one screen, SCREEN_RESOURCES is normally not used, +all resources are just placed in the RESOURCE_MANAGER property.) +.LP +The file specified by +.I filename +(or the contents from standard input if - or no filename is given) +is optionally passed through the C preprocessor with the +following symbols defined, based on the capabilities of the server +being used: +.TP 8 +.B SERVERHOST=\fIhostname\fP +the hostname portion of the display to which you are connected. +.TP 8 +.B SRVR_\fIname\fB +the SERVERHOST hostname string turned into a legal identifier. +For example, "my-dpy.lcs.mit.edu" becomes SRVR_my_dpy_lcs_mit_edu. +.TP 8 +.B HOST=\fIhostname\fP +the same as +.BR SERVERHOST . +.TP 8 +.B DISPLAY_NUM=\fInum\fP +the number of the display on the server host. +.TP 8 +.B CLIENTHOST=\fIhostname\fP +the name of the host on which +.I xrdb +is running. +.TP 8 +.B CLNT_\fIname\fB +the CLIENTHOST hostname string turned into a legal identifier. +For example, "expo.lcs.mit.edu" becomes CLNT_expo_lcs_mit_edu. +.TP 8 +.B RELEASE=\fInum\fP +the vendor release number for the server. The interpretation of this +number will vary depending on VENDOR. +.TP 8 +.B REVISION=\fInum\fP +the X protocol minor version supported by this server (currently 0). +.TP 8 +.B VERSION=\fInum\fP +the X protocol major version supported by this server (should always be 11). +.TP 8 +.B VENDOR="\fIvendor\fP" +a string literal specifying the vendor of the server. +.TP 8 +.B VNDR_\fIname\fP +the VENDOR name string turned into a legal identifier. +For example, "MIT X Consortium" becomes VNDR_MIT_X_Consortium. +.TP 8 +.B EXT_\fIname\fP +A symbol is defined for each protocol extension supported by the server. +Each extension string name is turned into a legal identifier. +For example, "X3D-PEX" becomes EXT_X3D_PEX. +.TP 8 +.B NUM_SCREENS=\fInum\fP +the total number of screens. +.TP 8 +.B SCREEN_NUM=\fInum\fP +the number of the current screen (from zero). +.TP 8 +.B BITS_PER_RGB=\fInum\fP +the number of significant bits in an RGB color specification. This is the +log base 2 of the number of distinct shades of each primary that the hardware +can generate. Note that it usually is not related to PLANES. +.TP 8 +.B CLASS=\fIvisualclass\fP +one of StaticGray, GrayScale, StaticColor, PseudoColor, TrueColor, +DirectColor. This is the visual class of the root window. +.TP 8 +.B CLASS_\fIvisualclass\fP=\fIvisualid\fP +the visual class of the root window in a form you can \fI#ifdef\fP on. +The value is the numeric id of the visual. +.TP 8 +.B COLOR +defined only if CLASS is one of StaticColor, PseudoColor, TrueColor, or +DirectColor. +.TP 8 +.B CLASS_\fIvisualclass\fP_\fIdepth\fP=\fInum\fP +A symbol is defined for each visual supported for the screen. +The symbol includes the class of the visual and its depth; +the value is the numeric id of the visual. +(If more than one visual has the same class and depth, the numeric id +of the first one reported by the server is used.) +.TP 8 +.B HEIGHT=\fInum\fP +the height of the root window in pixels. +.TP 8 +.B WIDTH=\fInum\fP +the width of the root window in pixels. +.TP 8 +.B PLANES=\fInum\fP +the number of bit planes (the depth) of the root window. +.TP 8 +.B X_RESOLUTION=\fInum\fP +the x resolution of the screen in pixels per meter. +.TP 8 +.B Y_RESOLUTION=\fInum\fP +the y resolution of the screen in pixels per meter. +.LP +SRVR_\fIname\fP, CLNT_\fIname\fP, VNDR_\fIname\fP, and EXT_\fIname\fP +identifiers are formed by changing all characters other than letters +and digits into underscores (_). +.LP +Lines that begin with an exclamation mark (!) are ignored and may +be used as comments. +.LP +Note that since +.I xrdb +can read from standard input, it can be used to +the change the contents of properties directly from +a terminal or from a shell script. +.SH "OPTIONS" +.PP +.I xrdb +program accepts the following options: +.TP 8 +.B \-help +This option (or any unsupported option) will cause a brief description of +the allowable options and parameters to be printed. +.TP 8 +.B \-display \fIdisplay\fP +This option specifies the X server to be used; see \fIX(__miscmansuffix__)\fP. +It also specifies the screen to use for the \fI-screen\fP option, +and it specifies the screen from which preprocessor symbols are +derived for the \fI-global\fP option. +.TP 8 +.B \-all +This option indicates that operation should be performed on the +screen-independent resource property (RESOURCE_MANAGER), as well as +the screen-specific property (SCREEN_RESOURCES) on every screen of the +display. For example, when used in conjunction with \fI-query\fP, +the contents of all properties are output. For \fI-load\fP, \fI-override\fP +and \fI-merge\fP, +the input file is processed once for each screen. The resources which occur +in common in the output for every screen are collected, and these are applied +as the screen-independent resources. The remaining resources are applied +for each individual per-screen property. This the default mode of operation. +.TP 8 +.B \-global +This option indicates that the operation should only be performed on +the screen-independent RESOURCE_MANAGER property. +.TP 8 +.B \-screen +This option indicates that the operation should only be performed on +the SCREEN_RESOURCES property of the default screen of the display. +.TP 8 +.B \-screens +This option indicates that the operation should be performed on +the SCREEN_RESOURCES property of each screen of the display. +For \fI-load\fP, \fI-override\fP and \fI-merge\fP, the input file is +processed for each screen. +.TP 8 +.B \-n +This option indicates that changes to the specified properties (when used with +\fI-load\fP, \fI-override\fP or \fI-merge\fP) +or to the resource file (when used with \fI-edit\fP) should be shown on the +standard output, but should not be performed. +.TP 8 +.B \-quiet +This option indicates that warning about duplicate entries should not be +displayed. +.TP 8 +.B -cpp \fIfilename\fP +This option specifies the pathname of the C preprocessor program to be used. +Although +.I xrdb +was designed to use CPP, any program that acts as a filter +and accepts the -D, -I, and -U options may be used. +.TP 8 +.B -nocpp +This option indicates that +.I xrdb +should not run the input file through a preprocessor before loading it +into properties. +.TP 8 +.B \-symbols +This option indicates that the symbols that are defined for the preprocessor +should be printed onto the standard output. +.TP 8 +.B \-query +This option indicates that the current contents of the specified +properties should be printed onto the standard output. Note that since +preprocessor commands in the input resource file are part of the input +file, not part of the property, they won't appear in the output from this +option. The +.B \-edit +option can be used to merge the contents of properties back into the input +resource file without damaging preprocessor commands. +.TP 8 +.B \-load +This option indicates that the input should be loaded as the new value +of the specified properties, replacing whatever was there (i.e. +the old contents are removed). This is the default action. +.TP 8 +.B \-override +This option indicates that the input should be added to, instead of +replacing, the current contents of the specified properties. +New entries override previous entries. +.TP 8 +.B \-merge +This option indicates that the input should be merged and lexicographically +sorted with, instead of replacing, the current contents of the specified +properties. +.TP 8 +.B \-remove +This option indicates that the specified properties should be removed +from the server. +.TP 8 +.B \-retain +This option indicates that the server should be instructed not to reset if +\fIxrdb\fP is the first client. This should never be necessary under normal +conditions, since \fIxdm\fP and \fIxinit\fP always act as the first client. +.TP 8 +.B \-edit \fIfilename\fP +This option indicates that the contents of the specified properties +should be edited into the given file, replacing any values already listed +there. This allows you to put changes that you have made to your defaults +back into your resource file, preserving any comments or preprocessor lines. +.TP 8 +.B \-backup \fIstring\fP +This option specifies a suffix to be appended to the filename used with +.B \-edit +to generate a backup file. +.TP 8 +.B \-D\fIname[=value]\fP +This option is passed through to the preprocessor and is used to define +symbols for use with conditionals such as +.I #ifdef. +.TP 8 +.B \-U\fIname\fP +This option is passed through to the preprocessor and is used to remove +any definitions of this symbol. +.TP 8 +.B \-I\fIdirectory\fP +This option is passed through to the preprocessor and is used to specify +a directory to search for files that are referenced with +.I #include. +.SH FILES +Generalizes \fI~/.Xdefaults\fP files. +.SH "SEE ALSO" +X(__miscmansuffix__), appres(__appmansuffix__), listres(__appmansuffix__), +Xlib Resource Manager documentation, Xt resource documentation +.SH ENVIRONMENT +.TP 8 +.B DISPLAY +to figure out which display to use. +.SH BUGS +.PP +The default for no arguments should be to query, not to overwrite, so that +it is consistent with other programs. +.SH AUTHORS +Bob Scheifler, Phil Karlton, rewritten from the original by Jim Gettys diff --git a/apps/xrdb/xrdb.c b/apps/xrdb/xrdb.c new file mode 100644 index 000000000..b7c9fa3aa --- /dev/null +++ b/apps/xrdb/xrdb.c @@ -0,0 +1,1408 @@ +/* + * xrdb - X resource manager database utility + * + */ + +/* + * COPYRIGHT 1987, 1991 + * DIGITAL EQUIPMENT CORPORATION + * MAYNARD, MASSACHUSETTS + * MASSACHUSETTS INSTITUTE OF TECHNOLOGY + * CAMBRIDGE, MASSACHUSETTS + * ALL RIGHTS RESERVED. + * + * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND + * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. + * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR + * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. + * + * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, + * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT + * SET FORTH ABOVE. + * + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Digital Equipment Corporation not be + * used in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. + */ + +/* + * this program is used to load, or dump the resource manager database + * in the server. + * + * Original Author: Jim Gettys, August 28, 1987 + * Extensively Modified: Phil Karlton, January 5, 1987 + * Modified a Bunch More: Bob Scheifler, February, 1991 + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/Xos.h> +#include <X11/Xmu/SysUtil.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <stdarg.h> + +#ifdef NEED_SYS_PARAM_H +# include <sys/param.h> /* defines MAXHOSTNAMELEN on BSD & Linux */ +#endif + +#ifdef NEED_NETDB_H +# include <netdb.h> /* defines MAXHOSTNAMELEN on Solaris */ +#endif + +#define SCREEN_RESOURCES "SCREEN_RESOURCES" + +#ifndef CPP +#ifdef __UNIXOS2__ +/* expected to be in path */ +#define CPP "cpp" +#else +#define CPP "/usr/lib/cpp" +#endif /* __UNIXOS2__ */ +#endif /* CPP */ + +#define INIT_BUFFER_SIZE 10000 +#define INIT_ENTRY_SIZE 500 + +#define RALL 0 +#define RGLOBAL 1 +#define RSCREEN 2 +#define RSCREENS 3 + +#define OPSYMBOLS 0 +#define OPQUERY 1 +#define OPREMOVE 2 +#define OPEDIT 3 +#define OPLOAD 4 +#define OPMERGE 5 +#define OPOVERRIDE 6 + +#define RESOURCE_PROPERTY_NAME "RESOURCE_MANAGER" +#define BACKUP_SUFFIX ".bak" /* for editting */ + +typedef struct _Entry { + char *tag, *value; + int lineno; + Bool usable; +} Entry; +typedef struct _Buffer { + char *buff; + int room, used; +} Buffer; +typedef struct _Entries { + Entry *entry; + int room, used; +} Entries; + +/* dynamically allocated strings */ +#define CHUNK_SIZE 4096 +typedef struct _String { + char *val; + int room, used; +} String; + +static char *ProgramName; +static Bool quiet = False; +static char tmpname[32]; +static char *filename = NULL; +#ifdef PATHETICCPP +static Bool need_real_defines = False; +static char tmpname2[32]; +#endif +#ifdef WIN32 +static char tmpname3[32]; +#endif +static int oper = OPLOAD; +static char *editFile = NULL; +static const char *cpp_program = NULL; +static const char* const cpp_locations[] = { CPP }; +static char *backup_suffix = BACKUP_SUFFIX; +static Bool dont_execute = False; +static String defines; +static int defines_base; +#define MAX_CMD_DEFINES 512 +static char *cmd_defines[MAX_CMD_DEFINES]; +static int num_cmd_defines = 0; +static String includes; +static Display *dpy; +static Buffer buffer; +static Entries newDB; + +static void fatal(char *, ...); +static void addstring ( String *arg, const char *s ); +static void addescapedstring ( String *arg, const char *s ); +static void addtokstring ( String *arg, const char *s ); +static void FormatEntries ( Buffer *buffer, Entries *entries ); +static void StoreProperty ( Display *dpy, Window root, Atom res_prop ); +static void Process ( int scrno, Bool doScreen, Bool execute ); +static void ShuffleEntries ( Entries *db, Entries *dbs, int num ); +static void ReProcess ( int scrno, Bool doScreen ); + +#ifndef HAVE_ASPRINTF +/* sprintf variant found in newer libc's which allocates string to print to */ +static int _X_ATTRIBUTE_PRINTF(2,3) +asprintf(char ** ret, const char *format, ...) +{ + char buf[256]; + int len; + va_list ap; + + va_start(ap, format); + len = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + if (len < 0) + return -1; + + if (len < sizeof(buf)) + { + *ret = strdup(buf); + } + else + { + *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */ + if (*ret != NULL) + { + va_start(ap, format); + len = vsnprintf(*ret, len + 1, format, ap); + va_end(ap); + if (len < 0) { + free(*ret); + *ret = NULL; + } + } + } + + if (*ret == NULL) + return -1; + + return len; +} +#endif /* HAVE_ASPRINTF */ + +static void +InitBuffer(Buffer *b) +{ + b->room = INIT_BUFFER_SIZE; + b->used = 0; + b->buff = (char *)malloc(INIT_BUFFER_SIZE*sizeof(char)); +} + +#ifdef notyet +static void +FreeBuffer(Buffer *b) +{ + free(b->buff); +} +#endif + +static void +AppendToBuffer(Buffer *b, char *str, int len) +{ + while (b->used + len > b->room) { + b->buff = (char *)realloc(b->buff, 2*b->room*(sizeof(char))); + b->room *= 2; + } + strncpy(b->buff + b->used, str, len); + b->used += len; +} + +static void +InitEntries(Entries *e) +{ + e->room = INIT_ENTRY_SIZE; + e->used = 0; + e->entry = (Entry *)malloc(INIT_ENTRY_SIZE*sizeof(Entry)); +} + +static void +FreeEntries(Entries *e) +{ + register int i; + + for (i = 0; i < e->used; i++) { + if (e->entry[i].usable) { + free(e->entry[i].tag); + free(e->entry[i].value); + } + } + free((char *)e->entry); +} + +static void +AddEntry(Entries *e, Entry *entry) +{ + register int n; + + for (n = 0; n < e->used; n++) { + if (!strcmp(e->entry[n].tag, entry->tag)) { + /* overwrite old entry */ + if (e->entry[n].lineno && !quiet) { + fprintf (stderr, + "%s: \"%s\" on line %d overrides entry on line %d\n", + ProgramName, entry->tag, entry->lineno, + e->entry[n].lineno); + } + free(e->entry[n].tag); + free(e->entry[n].value); + entry->usable = True; + e->entry[n] = *entry; + return; /* ok to leave, now there's only one of each tag in db */ + } + } + + if (e->used == e->room) { + e->entry = (Entry *)realloc((char *)e->entry, + 2*e->room*(sizeof(Entry))); + e->room *= 2; + } + entry->usable = True; + e->entry[e->used++] = *entry; +} + + +static int +CompareEntries(const void *e1, const void *e2) +{ + return strcmp(((Entry *)e1)->tag, ((Entry *)e2)->tag); +} + +static void +AppendEntryToBuffer(Buffer *buffer, Entry *entry) +{ + AppendToBuffer(buffer, entry->tag, strlen(entry->tag)); + AppendToBuffer(buffer, ":\t", 2); + AppendToBuffer(buffer, entry->value, strlen(entry->value)); + AppendToBuffer(buffer, "\n", 1); +} + +/* + * Return the position of the first unescaped occurrence of dest in string. + * If lines is non-null, return the number of newlines skipped over. + */ +static char * +FindFirst(char *string, char dest, int *lines) +{ + if (lines) + *lines = 0; + for (;;) { + if (*string == '\0') + return NULL; + if (*string == '\\') { + if (*++string == '\0') + return NULL; + } else if (*string == dest) + return string; + if (*string == '\n' && lines) + (*lines)++; + string++; + } +} + +static void +GetEntries(Entries *entries, Buffer *buff, int bequiet) +{ + register char *line, *colon, *temp, *str; + Entry entry; + register int length; + int lineno = 0; + int lines_skipped; + + str = buff->buff; + if (!str) return; + for ( ; str < buff->buff + buff->used; + str = line + 1, lineno += lines_skipped) { + line = FindFirst(str, '\n', &lines_skipped); + lineno++; + if (!line) + line = buff->buff + buff->used; + if (*str == '!') + continue; + if (*str == '\n') + continue; + if (!bequiet && *str == '#') { + int dummy; + if (sscanf (str, "# %d", &dummy) == 1 || + sscanf (str, "# line %d", &dummy) == 1) + lineno = dummy - 1; + continue; + } + for (temp = str; + *temp && *temp != '\n' && isascii(*temp) && isspace(*temp); + temp++) ; + if (!*temp || *temp == '\n') continue; + + colon = FindFirst(str, ':', NULL); + if (!colon || colon > line) { + if (!bequiet && !quiet) + fprintf (stderr, + "%s: colon missing on line %d, ignoring line\n", + ProgramName, lineno); + continue; + } + + /* strip leading and trailing blanks from name and store result */ + while (*str == ' ' || *str == '\t') + str++; + length = colon - str; + while (length && (str[length-1] == ' ' || str[length-1] == '\t')) + length--; + temp = (char *)malloc(length + 1); + strncpy(temp, str, length); + temp[length] = '\0'; + entry.tag = temp; + + /* strip leading and trailing blanks from value and store result */ + colon++; + while (*colon == ' ' || *colon == '\t') + colon++; + length = line - colon; + temp = (char *)malloc(length + 1); + strncpy(temp, colon, length); + temp[length] = '\0'; + entry.value = temp; + entry.lineno = bequiet ? 0 : lineno; + + AddEntry(entries, &entry); + } +} + +static void +GetEntriesString(Entries *entries, char *str) +{ + Buffer buff; + + if (str && *str) { + buff.buff = str; + buff.used = strlen(str); + GetEntries(entries, &buff, 1); + } +} + +static void +ReadFile(Buffer *buffer, FILE *input) +{ + char buf[BUFSIZ + 1]; + register int bytes; + + buffer->used = 0; + while (!feof(input) && (bytes = fread(buf, 1, BUFSIZ, input)) > 0) { +#ifdef WIN32 + char *p; + buf[bytes] = '\0'; + for (p = buf; p = strchr(p, '\r'); ) { + if (p[-1] == '\\' && p[1] == '\n') { + bytes -= 3; + strcpy(p - 1, p + 2); + } + } +#endif + AppendToBuffer(buffer, buf, bytes); + } + AppendToBuffer(buffer, "", 1); +} + +static void +AddDef(String *buff, char *title, char *value) +{ +#ifdef PATHETICCPP + if (need_real_defines) { + addstring(buff, "\n#define "); + addtokstring(buff, title); + if (value && (value[0] != '\0')) { + addstring(buff, " "); + addstring(buff, value); + } + return; + } +#endif + if (buff->used) { + if (oper == OPSYMBOLS) + addstring(buff, "\n-D"); + else + addstring(buff, " -D"); + } else + addstring(buff, "-D"); + addtokstring(buff, title); + if (value && (value[0] != '\0')) { + addstring(buff, "="); + addescapedstring(buff, value); + } +} + +static void +AddSimpleDef(String *buff, char *title) +{ + AddDef(buff, title, (char *)NULL); +} + +static void +AddDefQ(String *buff, char *title, char *value) +{ +#ifdef PATHETICCPP + if (need_real_defines) + AddDef(buff, title, value); + else +#endif + if (value && (value[0] != '\0')) { + AddSimpleDef(buff, title); + addstring(buff, "=\""); + addescapedstring(buff, value); + addstring(buff, "\""); + } else + AddDef(buff, title, NULL); +} + +static void +AddNum(String *buff, char *title, int value) +{ + char num[20]; + snprintf(num, sizeof(num), "%d", value); + AddDef(buff, title, num); +} + +static void +AddDefTok(String *buff, char *prefix, char *title) +{ + char name[512]; + + snprintf(name, sizeof(name), "%s%s", prefix, title); + AddSimpleDef(buff, name); +} + +static void +AddDefHostname(String *buff, char *title, char *value) +{ + char *s; + char name[512]; + char c; + + strncpy (name, value, sizeof(name)-1); + name[sizeof(name)-1] = '\0'; + for (s = name; (c = *s); s++) { + if (!isalpha(c) && !isdigit(c) && c != '_' && c != '.' && c != ':' && c != '-') + *s = '_'; + } + AddDef(buff, title, name); +} + +static void +AddUndef(String *buff, char *title) +{ +#ifdef PATHETICCPP + if (need_real_defines) { + addstring(buff, "\n#undef "); + addstring(buff, title); + return; + } +#endif + if (buff->used) { + if (oper == OPSYMBOLS) + addstring(buff, "\n-U"); + else + addstring(buff, " -U"); + } else + addstring(buff, "-U"); + addtokstring(buff, title); +} + +static void +DoCmdDefines(String *buff) +{ + int i; + char *arg, *val; + + for (i = 0; i < num_cmd_defines; i++) { + arg = cmd_defines[i]; + if (arg[1] == 'D') { + val = strchr(arg, '='); + if (val) { + *val = '\0'; + AddDefQ(buff, arg + 2, val + 1); + *val = '='; + } else + AddSimpleDef(buff, arg + 2); + } else + AddUndef(buff, arg + 2); + } +} + +static int +Resolution(int pixels, int mm) +{ + if (mm == 0) + return 0; + else + return ((pixels * 100000 / mm) + 50) / 100; +} + + +static void +DoDisplayDefines(Display *display, String *defs, char *host) +{ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 255 +#endif + char client[MAXHOSTNAMELEN], server[MAXHOSTNAMELEN], *colon; + char **extnames; + int n; + + XmuGetHostname(client, MAXHOSTNAMELEN); + strncpy(server, XDisplayName(host), sizeof(server)); + server[sizeof(server) - 1] = '\0'; + /* search for final colon to skip over any embedded colons in IPv6 + numeric address forms */ + colon = strrchr(server, ':'); + n = 0; + if (colon) { + /* remove extra colon if there are exactly two, since it indicates + DECnet. Three colons is an IPv6 address ending in :: though. */ + if ((colon > server) && (*(colon-1) == ':') && + ( ((colon - 1) == server) || (*(colon-2) != ':') ) ) { + *(colon-1) = ':'; + } + *colon++ = '\0'; + sscanf(colon, "%d", &n); + } + if (!*server || !strcmp(server, "unix") || !strcmp(server, "localhost")) + strcpy(server, client); + AddDefHostname(defs, "HOST", server); /* R3 compatibility */ + AddDefHostname(defs, "SERVERHOST", server); + AddDefTok(defs, "SRVR_", server); + AddNum(defs, "DISPLAY_NUM", n); + AddDefHostname(defs, "CLIENTHOST", client); + AddDefTok(defs, "CLNT_", client); + AddNum(defs, "VERSION", ProtocolVersion(display)); + AddNum(defs, "REVISION", ProtocolRevision(display)); + AddDefQ(defs, "VENDOR", ServerVendor(display)); + AddDefTok(defs, "VNDR_", ServerVendor(display)); + AddNum(defs, "RELEASE", VendorRelease(display)); + AddNum(defs, "NUM_SCREENS", ScreenCount(display)); + extnames = XListExtensions(display, &n); + while (--n >= 0) + AddDefTok(defs, "EXT_", extnames[n]); + XFreeExtensionList(extnames); +} + +static char *ClassNames[] = { + "StaticGray", + "GrayScale", + "StaticColor", + "PseudoColor", + "TrueColor", + "DirectColor" +}; + +static void +DoScreenDefines(Display *display, int scrno, String *defs) +{ + Screen *screen; + Visual *visual; + XVisualInfo vinfo, *vinfos; + int nv, i, j; + char name[50]; + + screen = ScreenOfDisplay(display, scrno); + visual = DefaultVisualOfScreen(screen); + vinfo.screen = scrno; + vinfos = XGetVisualInfo(display, VisualScreenMask, &vinfo, &nv); + AddNum(defs, "SCREEN_NUM", scrno); + AddNum(defs, "WIDTH", screen->width); + AddNum(defs, "HEIGHT", screen->height); + AddNum(defs, "X_RESOLUTION", Resolution(screen->width,screen->mwidth)); + AddNum(defs, "Y_RESOLUTION", Resolution(screen->height,screen->mheight)); + AddNum(defs, "PLANES", DisplayPlanes(display, scrno)); + AddNum(defs, "BITS_PER_RGB", visual->bits_per_rgb); + AddDefQ(defs, "CLASS", ClassNames[visual->class]); + snprintf(name, sizeof(name), "CLASS_%s", ClassNames[visual->class]); + AddNum(defs, name, (int)visual->visualid); + switch(visual->class) { + case StaticColor: + case PseudoColor: + case TrueColor: + case DirectColor: + AddSimpleDef(defs, "COLOR"); + break; + } + for (i = 0; i < nv; i++) { + for (j = i; --j >= 0; ) { + if (vinfos[j].class == vinfos[i].class && + vinfos[j].depth == vinfos[i].depth) + break; + } + if (j < 0) { + snprintf(name, sizeof(name), "CLASS_%s_%d", + ClassNames[vinfos[i].class], vinfos[i].depth); + AddNum(defs, name, (int)vinfos[i].visualid); + } + } + XFree((char *)vinfos); +} + +static Entry * +FindEntry(Entries *db, Buffer *b) +{ + int i; + register Entry *e; + Entries phoney; + Entry entry; + + entry.usable = False; + entry.tag = NULL; + entry.value = NULL; + phoney.used = 0; + phoney.room = 1; + phoney.entry = &entry; + GetEntries(&phoney, b, 1); + if (phoney.used < 1) + return NULL; + for (i = 0; i < db->used; i++) { + e = &db->entry[i]; + if (!e->usable) + continue; + if (strcmp(e->tag, entry.tag)) + continue; + e->usable = False; + if (strcmp(e->value, entry.value)) + return e; + return NULL; + } + return NULL; +} + +static void +EditFile(Entries *new, FILE *in, FILE *out) +{ + Buffer b; + char buff[BUFSIZ]; + register Entry *e; + register char *c; + int i; + + InitBuffer(&b); + while (in) { + b.used = 0; + while (1) { + buff[0] ='\0'; + if (!fgets(buff, BUFSIZ, in)) + goto cleanup; + AppendToBuffer(&b, buff, strlen(buff)); + c = &b.buff[b.used - 1]; + if ((*(c--) == '\n') && (b.used == 1 || *c != '\\')) + break; + } + if ((e = FindEntry(new, &b))) + fprintf(out, "%s:\t%s\n", e->tag, e->value); + else + fwrite(b.buff, 1, b.used, out); + } +cleanup: + for (i = 0; i < new->used; i++) { + e = &new->entry[i]; + if (e->usable) + fprintf(out, "%s:\t%s\n", e->tag, e->value); + } +} + +static void +Syntax (void) +{ + fprintf (stderr, + "usage: %s [-options ...] [filename]\n\n" + "where options include:\n" + " -display host:dpy display to use\n" + " -all do all resources [default]\n" + " -global do screen-independent resources\n" + " -screen do screen-specific resources for one screen\n" + " -screens do screen-specific resources for all screens\n" + " -n show but don't do changes\n" + " -cpp filename preprocessor to use [%s]\n" + " -nocpp do not use a preprocessor\n" + " -query query resources\n" + " -load load resources from file [default]\n" + " -override add in resources from file\n" + " -merge merge resources from file & sort\n" + " -edit filename edit resources into file\n" + " -backup string backup suffix for -edit [%s]\n" + " -symbols show preprocessor symbols\n" + " -remove remove resources\n" + " -retain avoid server reset (avoid using this)\n" + " -quiet don't warn about duplicates\n" + " -Dname[=value], -Uname, -Idirectory passed to preprocessor\n" + "\n" + "A - or no input filename represents stdin.\n", + ProgramName, cpp_program ? cpp_program : "", BACKUP_SUFFIX); + exit (1); +} + +/* + * The following is a hack until XrmParseCommand is ready. It determines + * whether or not the given string is an abbreviation of the arg. + */ + +static Bool +isabbreviation(char *arg, char *s, int minslen) +{ + int arglen; + int slen; + + /* exact match */ + if (!strcmp (arg, s)) return (True); + + arglen = strlen (arg); + slen = strlen (s); + + /* too long or too short */ + if (slen >= arglen || slen < minslen) return (False); + + /* abbreviation */ + if (strncmp (arg, s, slen) == 0) return (True); + + /* bad */ + return (False); +} + +static void +addstring(String *arg, const char *s) +{ + if(arg->used + strlen(s) + 1 >= arg->room) { + if(arg->val) + arg->val = (char *)realloc(arg->val, arg->room + CHUNK_SIZE); + else + arg->val = (char *)malloc(arg->room + CHUNK_SIZE); + if(arg->val == NULL) + fatal("%s: Not enough memory\n", ProgramName); + arg->room += CHUNK_SIZE; + } + if(arg->used) + strcat(arg->val, s); + else + strcpy(arg->val, s); + arg->used += strlen(s); +} + +static void +addescapedstring(String *arg, const char *s) +{ + char copy[512], *c; + + for (c = copy; *s && c < ©[sizeof(copy)-1]; s++) { + switch (*s) { + case '"': case '\'': case '`': + case '$': case '\\': + *c++ = '_'; + break; + default: + *c++ = *s; + } + } + *c = 0; + addstring (arg, copy); +} + +static void +addtokstring(String *arg, const char *s) +{ + char copy[512], *c; + + for (c = copy; *s && c < ©[sizeof(copy)-1]; s++) { + if (!isalpha(*s) && !isdigit(*s) && *s != '_') + *c++ = '_'; + else + *c++ = *s; + } + *c = 0; + addstring (arg, copy); +} + + +int +main(int argc, char *argv[]) +{ + int i; + char *displayname = NULL; + int whichResources = RALL; + int retainProp = 0; + FILE *fp = NULL; + Bool need_newline; + + ProgramName = argv[0]; + + defines.room = defines.used = includes.room = includes.used = 0; + + /* initialize the includes String struct */ + addstring(&includes, ""); + + /* Pick the default cpp to use. This needs to be done before + * we parse the command line in order to honor -nocpp which sets + * it back to NULL. + */ + if (cpp_program == NULL) { + int number_of_elements + = (sizeof cpp_locations) / (sizeof cpp_locations[0]); + int j; + + for (j = 0; j < number_of_elements; j++) { + char *end, *dup; + /* cut off arguments */ + dup = strdup(cpp_locations[j]); + end = strchr(dup,' '); + if (end) + *end = '\0'; + if (access(dup, X_OK) == 0) { + cpp_program = cpp_locations[j]; + free(dup); + break; + } + free(dup); + } + } + + /* needs to be replaced with XrmParseCommand */ + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + + if (arg[0] == '-') { + if (arg[1] == '\0') { + filename = NULL; + continue; + } else if (isabbreviation ("-help", arg, 2)) { + Syntax (); + /* doesn't return */ + } else if (isabbreviation ("-display", arg, 2)) { + if (++i >= argc) Syntax (); + displayname = argv[i]; + continue; + } else if (isabbreviation ("-geometry", arg, 3)) { + if (++i >= argc) Syntax (); + /* ignore geometry */ + continue; + } else if (isabbreviation ("-cpp", arg, 2)) { + if (++i >= argc) Syntax (); + cpp_program = argv[i]; + continue; + } else if (!strcmp ("-n", arg)) { + dont_execute = True; + continue; + } else if (isabbreviation ("-nocpp", arg, 3)) { + cpp_program = NULL; + continue; + } else if (isabbreviation ("-query", arg, 2)) { + oper = OPQUERY; + continue; + } else if (isabbreviation ("-load", arg, 2)) { + oper = OPLOAD; + continue; + } else if (isabbreviation ("-merge", arg, 2)) { + oper = OPMERGE; + continue; + } else if (isabbreviation ("-override", arg, 2)) { + oper = OPOVERRIDE; + continue; + } else if (isabbreviation ("-symbols", arg, 3)) { + oper = OPSYMBOLS; + continue; + } else if (isabbreviation ("-remove", arg, 4)) { + oper = OPREMOVE; + continue; + } else if (isabbreviation ("-edit", arg, 2)) { + if (++i >= argc) Syntax (); + oper = OPEDIT; + editFile = argv[i]; + continue; + } else if (isabbreviation ("-backup", arg, 2)) { + if (++i >= argc) Syntax (); + backup_suffix = argv[i]; + continue; + } else if (isabbreviation ("-all", arg, 2)) { + whichResources = RALL; + continue; + } else if (isabbreviation ("-global", arg, 3)) { + whichResources = RGLOBAL; + continue; + } else if (isabbreviation ("-screen", arg, 3)) { + whichResources = RSCREEN; + continue; + } else if (!strcmp ("-screens", arg)) { + whichResources = RSCREENS; + continue; + } else if (isabbreviation ("-retain", arg, 4)) { + retainProp = 1; + continue; + } else if (isabbreviation ("-quiet", arg, 2)) { + quiet = True; + continue; + } else if (arg[1] == 'I') { + addstring(&includes, " "); + addescapedstring(&includes, arg); + continue; + } else if (arg[1] == 'U' || arg[1] == 'D') { + if (num_cmd_defines < MAX_CMD_DEFINES) { + cmd_defines[num_cmd_defines++] = arg; + } else { + fatal("%s: Too many -U/-D arguments\n", ProgramName); + } + continue; + } + Syntax (); + } else if (arg[0] == '=') + continue; + else + filename = arg; + } /* end for */ + +#ifndef WIN32 + while ((i = open("/dev/null", O_RDONLY)) < 3) + ; /* make sure later freopen won't clobber things */ + (void) close(i); +#endif + /* Open display */ + if (!(dpy = XOpenDisplay (displayname))) + fatal("%s: Can't open display '%s'\n", ProgramName, + XDisplayName (displayname)); + + if (whichResources == RALL && ScreenCount(dpy) == 1) + whichResources = RGLOBAL; + +#ifdef PATHETICCPP + if (cpp_program && + (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE)) { + need_real_defines = True; +#ifdef WIN32 + strcpy(tmpname2, "xrdbD_XXXXXX"); + strcpy(tmpname3, "\\temp\\xrdbD_XXXXXX"); +#else +#ifdef __UNIXOS2__ + { char *tmpdir=getenv("TMP"); + if (!tmpdir) tmpdir="/"; + sprintf(tmpname2, "%s/xrdbD_XXXXXX",tmpdir); + } +#else + strcpy(tmpname2, "/tmp/xrdbD_XXXXXX"); +#endif +#endif + (void) mktemp(tmpname2); + } +#endif + + if (!filename && +#ifdef PATHETICCPP + need_real_defines +#else + (oper == OPLOAD || oper == OPMERGE || oper == OPOVERRIDE) && + (whichResources == RALL || whichResources == RSCREENS) +#endif + ) { + char inputbuf[1024]; +#ifdef WIN32 + strcpy(tmpname, "\\temp\\xrdb_XXXXXX"); +#else +#ifdef __UNIXOS2__ + { char *tmpdir=getenv("TMP"); + if (!tmpdir) tmpdir="/"; + sprintf(tmpname, "%s/xrdb_XXXXXX",tmpdir); + } +#else + strcpy(tmpname, "/tmp/xrdb_XXXXXX"); +#endif +#endif +#ifndef HAVE_MKSTEMP + (void) mktemp(tmpname); + filename = tmpname; + fp = fopen(filename, "w"); +#else + { + int fd = mkstemp(tmpname); + filename = tmpname; + fp = fdopen(fd, "w"); + } +#endif /* MKSTEMP */ + if (!fp) + fatal("%s: Failed to open temp file: %s\n", ProgramName, + filename); + while (fgets(inputbuf, sizeof(inputbuf), stdin) != NULL) + fputs(inputbuf, fp); + fclose(fp); + } + + DoDisplayDefines(dpy, &defines, displayname); + defines_base = defines.used; + need_newline = (oper == OPQUERY || oper == OPSYMBOLS || + (dont_execute && oper != OPREMOVE)); + InitBuffer(&buffer); + if (whichResources == RGLOBAL) + Process(DefaultScreen(dpy), False, True); + else if (whichResources == RSCREEN) + Process(DefaultScreen(dpy), True, True); + else if (whichResources == RSCREENS || + (oper != OPLOAD && oper != OPMERGE && oper != OPOVERRIDE)) { + if (whichResources == RALL && oper != OPSYMBOLS) { + if (need_newline) + printf("! screen-independent resources\n"); + Process(0, False, True); + if (need_newline) + printf("\n"); + } + for (i = 0; i < ScreenCount(dpy); i++) { + if (need_newline) { + if (oper == OPSYMBOLS) + printf("# screen %d symbols\n", i); + else { + printf("! screen %d resources\n", i); + printf("#if SCREEN_NUM == %d\n", i); + } + } + Process(i, True, True); + if (need_newline) { + if (oper != OPSYMBOLS) + printf("#endif\n"); + if (i+1 != ScreenCount(dpy)) + printf("\n"); + } + } + } + else { + Entries *dbs; + + dbs = (Entries *)malloc(ScreenCount(dpy) * sizeof(Entries)); + for (i = 0; i < ScreenCount(dpy); i++) { + Process(i, True, False); + dbs[i] = newDB; + } + InitEntries(&newDB); + if (oper == OPMERGE || oper == OPOVERRIDE) + GetEntriesString(&newDB, XResourceManagerString(dpy)); + ShuffleEntries(&newDB, dbs, ScreenCount(dpy)); + if (need_newline) + printf("! screen-independent resources\n"); + ReProcess(0, False); + if (need_newline) + printf("\n"); + for (i = 0; i < ScreenCount(dpy); i++) { + newDB = dbs[i]; + if (need_newline) { + printf("! screen %d resources\n", i); + printf("#if SCREEN_NUM == %d\n", i); + } + ReProcess(i, True); + if (need_newline) { + printf("#endif\n"); + if (i+1 != ScreenCount(dpy)) + printf("\n"); + } + } + } + + if (fp) + unlink(filename); + if (retainProp) + XSetCloseDownMode(dpy, RetainPermanent); + XCloseDisplay(dpy); + exit (0); +} + + +static void +FormatEntries(Buffer *buffer, Entries *entries) +{ + register int i; + + buffer->used = 0; + if (!entries->used) + return; + if (oper == OPMERGE) + qsort(entries->entry, entries->used, sizeof(Entry), + CompareEntries); + for (i = 0; i < entries->used; i++) { + if (entries->entry[i].usable) + AppendEntryToBuffer(buffer, &entries->entry[i]); + } +} + +static void +StoreProperty(Display *dpy, Window root, Atom res_prop) +{ + int len = buffer.used; + int mode = PropModeReplace; + unsigned char *buf = (unsigned char *)buffer.buff; + int max = (XMaxRequestSize(dpy) << 2) - 28; + + if (len > max) { + XGrabServer(dpy); + do { + XChangeProperty(dpy, root, res_prop, XA_STRING, 8, mode, buf, max); + buf += max; + len -= max; + mode = PropModeAppend; + } while (len > max); + } + XChangeProperty(dpy, root, res_prop, XA_STRING, 8, mode, buf, len); + if (mode != PropModeReplace) + XUngrabServer(dpy); +} + +static void +Process(int scrno, Bool doScreen, Bool execute) +{ + char *xdefs; + Window root; + Atom res_prop; + FILE *input, *output; + char *cmd; + + defines.val[defines_base] = '\0'; + defines.used = defines_base; + buffer.used = 0; + InitEntries(&newDB); + DoScreenDefines(dpy, scrno, &defines); + DoCmdDefines(&defines); + if (doScreen) { + xdefs = XScreenResourceString (ScreenOfDisplay(dpy, scrno)); + root = RootWindow(dpy, scrno); + res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False); + } else { + xdefs = XResourceManagerString (dpy); + root = RootWindow(dpy, 0); + res_prop = XA_RESOURCE_MANAGER; + } + if (oper == OPSYMBOLS) { + printf ("%s\n", defines.val); + } else if (oper == OPQUERY) { + if (xdefs) + printf ("%s", xdefs); /* fputs broken in SunOS 4.0 */ + } else if (oper == OPREMOVE) { + if (xdefs) + XDeleteProperty(dpy, root, res_prop); + } else if (oper == OPEDIT) { + char template[100], old[100]; + + input = fopen(editFile, "r"); + snprintf(template, sizeof(template), "%sXXXXXX", editFile); +#ifndef HAVE_MKSTEMP + (void) mktemp(template); + output = fopen(template, "w"); +#else + { + int fd = mkstemp(template); + output = fdopen(fd, "w"); + } +#endif + if (!output) + fatal("%s: can't open temporary file '%s'\n", ProgramName, template); + GetEntriesString(&newDB, xdefs); + EditFile(&newDB, input, output); + if (input) + fclose(input); + fclose(output); + snprintf(old, sizeof(old), "%s%s", editFile, backup_suffix); + if (dont_execute) { /* then write to standard out */ + char buf[BUFSIZ]; + int n; + + output = fopen (template, "r"); + if (output) { + while ((n = fread (buf, 1, sizeof buf, output)) > 0) { + fwrite (buf, 1, n, stdout); + } + fclose (output); + } + unlink (template); + } else { + rename (editFile, old); + if (rename (template, editFile)) + fatal("%s: can't rename file '%s' to '%s'\n", ProgramName, + template, editFile); + } + } else { + if (oper == OPMERGE || oper == OPOVERRIDE) + GetEntriesString(&newDB, xdefs); +#ifdef PATHETICCPP + if (need_real_defines) { +#ifdef WIN32 + if (!(input = fopen(tmpname2, "w"))) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname2); + fputs(defines.val, input); + fprintf(input, "\n#include \"%s\"\n", filename); + fclose(input); + (void) mktemp(tmpname3); + if (asprintf(&cmd, "%s -P%s %s > %s", cpp_program, includes.val, + tmpname2, tmpname3) == -1) + fatal("%s: Out of memory\n", ProgramName); + if (system(cmd) < 0) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); + free(cmd); + if (!(input = fopen(tmpname3, "r"))) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname3); +#else + if (!freopen(tmpname2, "w+", stdin)) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname2); + fputs(defines.val, stdin); + fprintf(stdin, "\n#include \"%s\"\n", filename); + fflush(stdin); + fseek(stdin, 0, 0); + if (asprintf(&cmd, "%s -P%s", cpp_program, includes.val) == -1) + fatal("%s: Out of memory\n", ProgramName); + if (!(input = popen(cmd, "r"))) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); + free(cmd); +#endif + } else { +#endif + if (filename) { + if (!freopen (filename, "r", stdin)) + fatal("%s: can't open file '%s'\n", ProgramName, filename); + } + if (cpp_program) { +#ifdef WIN32 + (void) mktemp(tmpname3); + if (asprintf(&cmd, "%s -P%s %s %s > %s", cpp_program, + includes.val, defines.val, + filename ? filename : "", tmpname3) == -1) + fatal("%s: Out of memory\n", ProgramName); + if (system(cmd) < 0) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); + free(cmd); + if (!(input = fopen(tmpname3, "r"))) + fatal("%s: can't open file '%s'\n", ProgramName, tmpname3); +#else + if (asprintf(&cmd, "%s -P%s %s %s", cpp_program, + includes.val, defines.val, + filename ? filename : "") == -1) + fatal("%s: Out of memory\n", ProgramName); + if (!(input = popen(cmd, "r"))) + fatal("%s: cannot run '%s'\n", ProgramName, cmd); + free(cmd); +#endif + } else { + input = stdin; + } +#ifdef PATHETICCPP + } +#endif + ReadFile(&buffer, input); + if (cpp_program) { +#ifdef WIN32 + fclose(input); +#else + pclose(input); +#endif + } +#ifdef PATHETICCPP + if (need_real_defines) { + unlink(tmpname2); +#ifdef WIN32 + if (tmpname3[strlen(tmpname3) - 1] != 'X') + unlink(tmpname3); +#endif + } +#endif + GetEntries(&newDB, &buffer, 0); + if (execute) { + FormatEntries(&buffer, &newDB); + if (dont_execute) { + if (buffer.used > 0) { + fwrite (buffer.buff, 1, buffer.used, stdout); + if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n'); + } + } else if (buffer.used > 1 || !doScreen) + StoreProperty (dpy, root, res_prop); + else + XDeleteProperty (dpy, root, res_prop); + } + } + if (execute) + FreeEntries(&newDB); + if (doScreen && xdefs) + XFree(xdefs); +} + +static void +ShuffleEntries(Entries *db, Entries *dbs, int num) +{ + int *hits; + register int i, j, k; + Entries cur, cmp; + char *curtag, *curvalue; + + hits = (int *)malloc(num * sizeof(int)); + cur = dbs[0]; + for (i = 0; i < cur.used; i++) { + curtag = cur.entry[i].tag; + curvalue = cur.entry[i].value; + for (j = 1; j < num; j++) { + cmp = dbs[j]; + for (k = 0; k < cmp.used; k++) { + if (cmp.entry[k].usable && + !strcmp(curtag, cmp.entry[k].tag) && + !strcmp(curvalue, cmp.entry[k].value)) + { + hits[j] = k; + break; + } + } + if (k == cmp.used) + break; + } + if (j == num) { + AddEntry(db, &cur.entry[i]); + hits[0] = i; + for (j = 0; j < num; j++) + dbs[j].entry[hits[j]].usable = False; + } + } + free((char *)hits); +} + +static void +ReProcess(int scrno, Bool doScreen) +{ + Window root; + Atom res_prop; + + FormatEntries(&buffer, &newDB); + if (doScreen) { + root = RootWindow(dpy, scrno); + res_prop = XInternAtom(dpy, SCREEN_RESOURCES, False); + } else { + root = RootWindow(dpy, 0); + res_prop = XA_RESOURCE_MANAGER; + } + if (dont_execute) { + if (buffer.used > 0) { + fwrite (buffer.buff, 1, buffer.used, stdout); + if (buffer.buff[buffer.used - 1] != '\n') putchar ('\n'); + } + } else { + if (buffer.used > 1 || !doScreen) + StoreProperty (dpy, root, res_prop); + else + XDeleteProperty (dpy, root, res_prop); + } + FreeEntries(&newDB); +} + +static void +fatal(char *msg, ...) +{ + va_list args; + + if (errno != 0) + perror(ProgramName); + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + exit(1); +} |