summaryrefslogtreecommitdiffstats
path: root/kdm/backend/resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'kdm/backend/resource.c')
-rw-r--r--kdm/backend/resource.c486
1 files changed, 486 insertions, 0 deletions
diff --git a/kdm/backend/resource.c b/kdm/backend/resource.c
new file mode 100644
index 000000000..f17db78ec
--- /dev/null
+++ b/kdm/backend/resource.c
@@ -0,0 +1,486 @@
+/*
+
+Copyright 1988, 1998 The Open Group
+Copyright 2000-2005 Oswald Buddenhagen <[email protected]>
+
+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 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.
+
+Except as contained in this notice, the name of a copyright holder 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 copyright holder.
+
+*/
+
+/*
+ * xdm - display manager daemon
+ * Author: Keith Packard, MIT X Consortium
+ *
+ * obtain configuration data
+ */
+
+#include "dm.h"
+#include "dm_error.h"
+
+#include <sys/stat.h>
+
+
+static char **originalArgv;
+
+static GProc getter;
+GTalk cnftalk;
+
+static void
+OpenGetter()
+{
+ GSet( &cnftalk );
+ if (!getter.pid) {
+ if (GOpen( &getter,
+ originalArgv, "_config", 0, strdup( "config reader" ),
+ 0 ))
+ LogPanic( "Cannot run config reader\n" );
+ Debug( "getter now ready\n" );
+ }
+}
+
+void
+CloseGetter()
+{
+ if (getter.pid) {
+ GSet( &cnftalk );
+ (void)GClose (&getter, 0, 0);
+ Debug( "getter now closed\n" );
+ }
+}
+
+/*
+ * ref-counted, unique-instance strings
+ */
+static RcStr *strs;
+
+/*
+ * make a ref-counted string of the argument. the new string will
+ * have a ref-count of 1. the passed string pointer is no longer valid.
+ */
+RcStr *
+newStr( char *str )
+{
+ RcStr *cs;
+
+ for (cs = strs; cs; cs = cs->next)
+ if (!strcmp( str, cs->str )) {
+ free( str );
+ cs->cnt++;
+ return cs;
+ }
+ if (!(cs = Malloc( sizeof(*cs) )))
+ return 0;
+ cs->cnt = 1;
+ cs->str = str;
+ cs->next = strs;
+ strs = cs;
+ return cs;
+}
+
+/*
+ * decrement ref-count and delete string when count drops to 0.
+ */
+void
+delStr( RcStr *str )
+{
+ RcStr **cs;
+
+ if (!str || --str->cnt)
+ return;
+ for (cs = &strs; *cs; cs = &((*cs)->next))
+ if (str == *cs) {
+ *cs = (*cs)->next;
+ free( (*cs)->str );
+ free( *cs );
+ break;
+ }
+}
+
+
+typedef struct CfgFile {
+ RcStr *name;
+ int depidx;
+ long deptime;
+} CfgFile;
+
+static int numCfgFiles;
+static CfgFile *cfgFiles;
+
+static int cfgMapT[] = {
+ GC_gGlobal,
+ GC_gDisplay,
+#ifdef XDMCP
+ GC_gXaccess,
+#endif
+};
+static int cfgMap[as(cfgMapT)];
+
+static int
+GetDeps()
+{
+ int ncf, i, dep, ret;
+ CfgFile *cf;
+
+ OpenGetter();
+ GSendInt( GC_Files );
+ ncf = GRecvInt();
+ if (!(cf = Malloc( ncf * sizeof(*cf) ))) {
+ CloseGetter();
+ return 0;
+ }
+ for (i = 0; i < ncf; i++) {
+ cf[i].name = newStr( GRecvStr() );
+ if ((dep = cf[i].depidx = GRecvInt()) != -1)
+ cf[i].deptime = mTime( cf[dep].name->str );
+ }
+ if (cfgFiles) {
+ for (i = 0; i < numCfgFiles; i++)
+ delStr( cfgFiles[i].name );
+ free( cfgFiles );
+ }
+ ret = 1;
+ cfgFiles = cf;
+ numCfgFiles = ncf;
+ for (i = 0; i < as(cfgMapT); i++) {
+ GSendInt( cfgMapT[i] );
+ if ((cfgMap[i] = GRecvInt()) < 0) {
+ LogError( "Config reader does not support config cathegory %#x\n",
+ cfgMapT[i] );
+ ret = 0;
+ }
+ }
+ GSendInt( -1 );
+ return ret;
+}
+
+static int
+checkDep( int idx )
+{
+ int dep;
+
+ if ((dep = cfgFiles[idx].depidx) == -1)
+ return 0;
+ if (checkDep( dep ))
+ return 1;
+ return mTime( cfgFiles[dep].name->str ) != cfgFiles[idx].deptime;
+}
+
+static int
+needsReScan( int what, CfgDep *dep )
+{
+ int widx, idx;
+ long mt;
+
+ for (widx = 0; cfgMapT[widx] != what; widx++);
+ idx = cfgMap[widx];
+ if (checkDep( idx )) {
+ if (!GetDeps())
+ return -1;
+ idx = cfgMap[widx];
+ }
+ mt = mTime( cfgFiles[idx].name->str );
+ if (dep->name != cfgFiles[idx].name) {
+ if (dep->name)
+ delStr( dep->name );
+ dep->name = cfgFiles[idx].name;
+ dep->name->cnt++;
+ dep->time = mt;
+ return 1;
+ } else if (dep->time != mt) {
+ dep->time = mt;
+ return 1;
+ } else
+ return 0;
+}
+
+int
+startConfig( int what, CfgDep *dep, int force )
+{
+ int ret;
+
+ if ((ret = needsReScan( what, dep )) < 0 || (!ret && !force))
+ return ret;
+ OpenGetter();
+ GSendInt( GC_GetConf );
+ GSendInt( what );
+ GSendStr( dep->name->str );
+ return 1;
+}
+
+static void
+LoadResources( CfgArr *conf )
+{
+ char **vptr, **pptr, *cptr;
+ long *iptr, i, id, nu, j, nptr, nint, nchr;
+
+ if (conf->data)
+ free( conf->data );
+ conf->numCfgEnt = GRecvInt();
+ nptr = GRecvInt();
+ nint = GRecvInt();
+ nchr = GRecvInt();
+ if (!(conf->data = Malloc( conf->numCfgEnt *
+ (sizeof(long) +
+ sizeof(char *)) +
+ nptr * sizeof(char *) +
+ nint * sizeof(long) +
+ nchr )))
+ {
+ CloseGetter();
+ return;
+ }
+ vptr = (char **)conf->data;
+ pptr = vptr + conf->numCfgEnt;
+ conf->idx = (long *)(pptr + nptr);
+ iptr = conf->idx + conf->numCfgEnt;
+ cptr = (char *)(iptr + nint);
+ for (i = 0; i < conf->numCfgEnt; i++) {
+ id = GRecvInt();
+ conf->idx[i] = id;
+ switch (id & C_TYPE_MASK) {
+ case C_TYPE_INT:
+ vptr[i] = (char *)((unsigned long)GRecvInt());
+ break;
+ case C_TYPE_STR:
+ vptr[i] = cptr;
+ cptr += GRecvStrBuf( cptr );
+ break;
+ case C_TYPE_ARGV:
+ nu = GRecvInt();
+ vptr[i] = (char *)pptr;
+ for (j = 0; j < nu; j++) {
+ *pptr++ = cptr;
+ cptr += GRecvStrBuf( cptr );
+ }
+ *pptr++ = (char *)0;
+ break;
+ default:
+ LogError( "Config reader supplied unknown data type in id %#x\n",
+ id );
+ break;
+ }
+ }
+}
+
+static void
+ApplyResource( int id, char **src, char **dst )
+{
+ switch (id & C_TYPE_MASK) {
+ case C_TYPE_INT:
+ *(int *)dst = *(long *)src;
+ break;
+ case C_TYPE_STR:
+ case C_TYPE_ARGV:
+ *dst = *src;
+ break;
+ }
+}
+
+
+#define boffset(f) XtOffsetOf(struct display, f)
+
+/* no global variables exported currently
+struct globEnts {
+ int id;
+ char **off;
+} globEnt[] = {
+};
+ */
+
+/* no per-display variables exported currently
+struct dpyEnts {
+ int id;
+ int off;
+} dpyEnt[] = {
+};
+ */
+
+CfgArr cfg;
+
+char **
+FindCfgEnt( struct display *d, int id )
+{
+ int i;
+
+/* no global variables exported currently
+ for (i = 0; i < as(globEnt); i++)
+ if (globEnt[i].id == id)
+ return globEnt[i].off;
+ */
+ for (i = 0; i < cfg.numCfgEnt; i++)
+ if (cfg.idx[i] == id)
+ return ((char **)cfg.data) + i;
+ if (d) {
+/* no per-display variables exported currently
+ for (i = 0; i < as(dpyEnt); i++)
+ if (dpyEnt[i].id == id)
+ return (char **)(((char *)d) + dpyEnt[i].off);
+ */
+ for (i = 0; i < d->cfg.numCfgEnt; i++)
+ if (d->cfg.idx[i] == id)
+ return ((char **)d->cfg.data) + i;
+ }
+ Debug( "unknown config entry %#x requested\n", id );
+ return (char **)0;
+}
+
+
+CONF_CORE_GLOBAL_DEFS
+
+struct globVals {
+ int id;
+ char **off;
+} globVal[] = {
+CONF_CORE_GLOBALS
+};
+
+int
+LoadDMResources( int force )
+{
+ int i, ret;
+ char **ent;
+
+ if (Setjmp( cnftalk.errjmp ))
+ return -1; /* may memleak, but we probably have to abort anyway */
+ if ((ret = startConfig( GC_gGlobal, &cfg.dep, force )) <= 0)
+ return ret;
+ LoadResources( &cfg );
+/* Debug( "manager resources: %[*x\n",
+ cfg.numCfgEnt, ((char **)cfg.data) + cfg.numCfgEnt );*/
+ ret = 1;
+ for (i = 0; i < as(globVal); i++) {
+ if (!(ent = FindCfgEnt( 0, globVal[i].id )))
+ ret = -1;
+ else
+ ApplyResource( globVal[i].id, ent, globVal[i].off );
+ }
+ if (ret < 0)
+ LogError( "Internal error: config reader supplied incomplete data\n" );
+ return ret;
+}
+
+
+struct dpyVals {
+ int id;
+ int off;
+} dpyVal[] = {
+CONF_CORE_LOCALS
+};
+
+int
+LoadDisplayResources( struct display *d )
+{
+ int i, ret;
+ char **ent;
+
+ if (Setjmp( cnftalk.errjmp ))
+ return -1; /* may memleak */
+ if ((ret = startConfig( GC_gDisplay, &d->cfg.dep, FALSE )) <= 0)
+ return ret;
+ GSendStr( d->name );
+ GSendStr( d->class2 );
+ LoadResources( &d->cfg );
+/* Debug( "display(%s, %s) resources: %[*x\n", d->name, d->class2,
+ d->cfg.numCfgEnt, ((char **)d->cfg.data) + d->cfg.numCfgEnt );*/
+ ret = 1;
+ for (i = 0; i < as(dpyVal); i++) {
+ if (!(ent = FindCfgEnt( d, dpyVal[i].id )))
+ ret = -1;
+ else
+ ApplyResource( dpyVal[i].id, ent,
+ (char **)(((char *)d) + dpyVal[i].off) );
+ }
+ if (ret < 0)
+ LogError( "Internal error: config reader supplied incomplete data\n" );
+ return ret;
+}
+
+int
+InitResources( char **argv )
+{
+ originalArgv = argv;
+ cnftalk.pipe = &getter.pipe;
+ if (Setjmp( cnftalk.errjmp ))
+ return 0; /* may memleak */
+ return GetDeps();
+}
+
+static void
+addServers( char **srv, int bType )
+{
+ char *name, *class2;
+ const char *dtx, *cls;
+ struct display *d;
+
+ for (; *srv; srv++) {
+ if ((cls = strchr( *srv, '_' ))) {
+ if (!StrNDup( &name, *srv, cls - *srv ))
+ return;
+ if (!StrDup( &class2, cls )) {
+ free( name );
+ return;
+ }
+ } else {
+ if (!StrDup( &name, *srv ))
+ return;
+ class2 = 0;
+ }
+ if ((d = FindDisplayByName( name ))) {
+ if (d->class2)
+ free( d->class2 );
+ dtx = "existing";
+ } else {
+ if (!(d = NewDisplay( name ))) {
+ free( name );
+ if (class2)
+ free( class2 );
+ return;
+ }
+ dtx = "new";
+ }
+ d->stillThere = 1;
+ d->class2 = class2;
+ d->displayType = (*name == ':' ? dLocal : dForeign) | bType;
+ if ((bType & d_lifetime) == dReserve) {
+ if (d->status == notRunning)
+ d->status = reserve;
+ } else {
+ if (d->status == reserve)
+ d->status = notRunning;
+ }
+ Debug( "found %s %s%s display: %s %s\n", dtx,
+ ((d->displayType & d_location) == dLocal) ? "local" : "foreign",
+ ((d->displayType & d_lifetime) == dReserve) ? " reserve" : "",
+ d->name, d->class2 );
+ free( name );
+ }
+}
+
+void
+ScanServers( void )
+{
+ Debug( "ScanServers\n" );
+ addServers( staticServers, dFromFile | dPermanent );
+ addServers( reserveServers, dFromFile | dReserve );
+}
+