add more spacing
[personal-kdebase.git] / workspace / kdm / backend / resource.c
blob6fac8a3e595ee1e8c4b4b1890d8a5755da777359
1 /*
3 Copyright 1988, 1998 The Open Group
4 Copyright 2000-2005 Oswald Buddenhagen <ossi@kde.org>
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of a copyright holder shall
24 not be used in advertising or otherwise to promote the sale, use or
25 other dealings in this Software without prior written authorization
26 from the copyright holder.
31 * xdm - display manager daemon
32 * Author: Keith Packard, MIT X Consortium
34 * obtain configuration data
37 #include "dm.h"
38 #include "dm_error.h"
40 #include <sys/stat.h>
42 #define WANT_CORE_DEFS
43 #include <config.ci>
45 static char **originalArgv;
47 static GProc getter;
48 GTalk cnftalk;
50 static void
51 openGetter()
53 gSet( &cnftalk );
54 if (!getter.pid) {
55 if (gOpen( &getter,
56 originalArgv, "_config", 0, strdup( "config reader" ),
57 0 ))
58 logPanic( "Cannot run config reader\n" );
59 debug( "getter now ready\n" );
63 void
64 closeGetter()
66 if (getter.pid) {
67 gSet( &cnftalk );
68 (void)gClose( &getter, 0, False );
69 debug( "getter now closed\n" );
74 * ref-counted, unique-instance strings
76 static RcStr *strs;
79 * make a ref-counted string of the argument. the new string will
80 * have a ref-count of 1. the passed string pointer is no longer valid.
82 RcStr *
83 newStr( char *str )
85 RcStr *cs;
87 for (cs = strs; cs; cs = cs->next)
88 if (!strcmp( str, cs->str )) {
89 free( str );
90 cs->cnt++;
91 return cs;
93 if (!(cs = Malloc( sizeof(*cs) )))
94 return 0;
95 cs->cnt = 1;
96 cs->str = str;
97 cs->next = strs;
98 strs = cs;
99 return cs;
103 * decrement ref-count and delete string when count drops to 0.
105 void
106 delStr( RcStr *str )
108 RcStr **cs;
110 if (!str || --str->cnt)
111 return;
112 for (cs = &strs; *cs; cs = &((*cs)->next))
113 if (str == *cs) {
114 *cs = (*cs)->next;
115 free( (*cs)->str );
116 free( *cs );
117 break;
122 typedef struct CfgFile {
123 RcStr *name;
124 int depidx;
125 long deptime;
126 } CfgFile;
128 static int numCfgFiles;
129 static CfgFile *cfgFiles;
131 static int cfgMapT[] = {
132 GC_gGlobal,
133 GC_gDisplay,
134 #ifdef XDMCP
135 GC_gXaccess,
136 #endif
138 static int cfgMap[as(cfgMapT)];
140 static int
141 getDeps()
143 int ncf, i, dep, ret;
144 CfgFile *cf;
146 openGetter();
147 gSendInt( GC_Files );
148 ncf = gRecvInt();
149 if (!(cf = Malloc( ncf * sizeof(*cf) ))) {
150 closeGetter();
151 return False;
153 for (i = 0; i < ncf; i++) {
154 cf[i].name = newStr( gRecvStr() );
155 if ((dep = cf[i].depidx = gRecvInt()) != -1)
156 cf[i].deptime = mTime( cf[dep].name->str );
158 if (cfgFiles) {
159 for (i = 0; i < numCfgFiles; i++)
160 delStr( cfgFiles[i].name );
161 free( cfgFiles );
163 ret = True;
164 cfgFiles = cf;
165 numCfgFiles = ncf;
166 for (i = 0; i < as(cfgMapT); i++) {
167 gSendInt( cfgMapT[i] );
168 if ((cfgMap[i] = gRecvInt()) < 0) {
169 logError( "Config reader does not support config cathegory %#x\n",
170 cfgMapT[i] );
171 ret = False;
174 gSendInt( -1 );
175 return ret;
178 static int
179 checkDep( int idx )
181 int dep;
183 if ((dep = cfgFiles[idx].depidx) == -1)
184 return False;
185 if (checkDep( dep ))
186 return True;
187 return mTime( cfgFiles[dep].name->str ) != cfgFiles[idx].deptime;
190 static int
191 needsReScan( int what, CfgDep *dep )
193 int widx, idx;
194 long mt;
196 for (widx = 0; cfgMapT[widx] != what; widx++);
197 idx = cfgMap[widx];
198 if (checkDep( idx )) {
199 if (!getDeps())
200 return -1;
201 idx = cfgMap[widx];
203 mt = mTime( cfgFiles[idx].name->str );
204 if (dep->name != cfgFiles[idx].name) {
205 if (dep->name)
206 delStr( dep->name );
207 dep->name = cfgFiles[idx].name;
208 dep->name->cnt++;
209 dep->time = mt;
210 return 1;
211 } else if (dep->time != mt) {
212 dep->time = mt;
213 return 1;
214 } else
215 return 0;
219 startConfig( int what, CfgDep *dep, int force )
221 int ret;
223 if ((ret = needsReScan( what, dep )) < 0 || (!ret && !force))
224 return ret;
225 openGetter();
226 gSendInt( GC_GetConf );
227 gSendInt( what );
228 gSendStr( dep->name->str );
229 return 1;
232 static void
233 loadResources( CfgArr *conf )
235 char **vptr, **pptr, *cptr;
236 int *iptr, i, id, nu, j, nptr, nint, nchr;
238 if (conf->data)
239 free( conf->data );
240 conf->numCfgEnt = gRecvInt();
241 nptr = gRecvInt();
242 nint = gRecvInt();
243 nchr = gRecvInt();
244 if (!(conf->data = Malloc( conf->numCfgEnt *
245 (sizeof(int) +
246 sizeof(char *)) +
247 nptr * sizeof(char *) +
248 nint * sizeof(int) +
249 nchr )))
251 closeGetter();
252 return;
254 vptr = (char **)conf->data;
255 pptr = vptr + conf->numCfgEnt;
256 conf->idx = (int *)(pptr + nptr);
257 iptr = conf->idx + conf->numCfgEnt;
258 cptr = (char *)(iptr + nint);
259 for (i = 0; i < conf->numCfgEnt; i++) {
260 id = gRecvInt();
261 conf->idx[i] = id;
262 switch (id & C_TYPE_MASK) {
263 case C_TYPE_INT:
264 vptr[i] = (char *)((unsigned long)gRecvInt());
265 break;
266 case C_TYPE_STR:
267 vptr[i] = cptr;
268 cptr += gRecvStrBuf( cptr );
269 break;
270 case C_TYPE_ARGV:
271 nu = gRecvInt();
272 vptr[i] = (char *)pptr;
273 for (j = 0; j < nu; j++) {
274 *pptr++ = cptr;
275 cptr += gRecvStrBuf( cptr );
277 *pptr++ = (char *)0;
278 break;
279 default:
280 logError( "Config reader supplied unknown data type in id %#x\n",
281 id );
282 break;
287 static void
288 applyResource( int id, void **src, void **dst )
290 switch (id & C_TYPE_MASK) {
291 case C_TYPE_INT:
292 *(int *)dst = *(int *)src;
293 break;
294 case C_TYPE_STR:
295 case C_TYPE_ARGV:
296 *(char **)dst = *(char **)src;
297 break;
302 #define boffset(f) offsetof(struct display, f)
304 /* no global variables exported currently
305 struct globEnts {
306 int id;
307 char **off;
308 } globEnt[] = {
312 /* no per-display variables exported currently
313 struct dpyEnts {
314 int id;
315 int off;
316 } dpyEnt[] = {
320 CfgArr cfg;
322 void **
323 findCfgEnt( struct display *d, int id )
325 int i;
327 /* no global variables exported currently
328 for (i = 0; i < as(globEnt); i++)
329 if (globEnt[i].id == id)
330 return globEnt[i].off;
332 for (i = 0; i < cfg.numCfgEnt; i++)
333 if (cfg.idx[i] == id)
334 return ((void **)cfg.data) + i;
335 if (d) {
336 /* no per-display variables exported currently
337 for (i = 0; i < as(dpyEnt); i++)
338 if (dpyEnt[i].id == id)
339 return (char **)(((char *)d) + dpyEnt[i].off);
341 for (i = 0; i < d->cfg.numCfgEnt; i++)
342 if (d->cfg.idx[i] == id)
343 return ((void **)d->cfg.data) + i;
345 debug( "unknown config entry %#x requested\n", id );
346 return (void **)0;
350 CONF_CORE_GLOBAL_DEFS
352 struct globVals {
353 int id;
354 void *ptr;
355 } globVal[] = {
356 CONF_CORE_GLOBALS
360 loadDMResources( int force )
362 int i, ret;
363 void **ent;
365 if (Setjmp( cnftalk.errjmp ))
366 return -1; /* may memleak, but we probably have to abort anyway */
367 if ((ret = startConfig( GC_gGlobal, &cfg.dep, force )) <= 0)
368 return ret;
369 loadResources( &cfg );
370 /* debug( "manager resources: %[*x\n",
371 cfg.numCfgEnt, ((char **)cfg.data) + cfg.numCfgEnt );*/
372 ret = 1;
373 for (i = 0; i < as(globVal); i++) {
374 if (!(ent = findCfgEnt( 0, globVal[i].id )))
375 ret = -1;
376 else
377 applyResource( globVal[i].id, ent, (void **)globVal[i].ptr );
379 if (ret < 0)
380 logError( "Internal error: config reader supplied incomplete data\n" );
381 return ret;
385 struct dpyVals {
386 int id;
387 int off;
388 } dpyVal[] = {
389 CONF_CORE_LOCALS
393 loadDisplayResources( struct display *d )
395 int i, ret;
396 void **ent;
398 if (Setjmp( cnftalk.errjmp ))
399 return -1; /* may memleak */
400 if ((ret = startConfig( GC_gDisplay, &d->cfg.dep, False )) <= 0)
401 return ret;
402 gSendStr( d->name );
403 gSendStr( d->class2 );
404 loadResources( &d->cfg );
405 /* debug( "display(%s, %s) resources: %[*x\n", d->name, d->class2,
406 d->cfg.numCfgEnt, ((char **)d->cfg.data) + d->cfg.numCfgEnt );*/
407 ret = 1;
408 for (i = 0; i < as(dpyVal); i++) {
409 if (!(ent = findCfgEnt( d, dpyVal[i].id )))
410 ret = -1;
411 else
412 applyResource( dpyVal[i].id, ent,
413 (void **)(((char *)d) + dpyVal[i].off) );
415 if (ret < 0)
416 logError( "Internal error: config reader supplied incomplete data\n" );
417 return ret;
421 initResources( char **argv )
423 originalArgv = argv;
424 cnftalk.pipe = &getter.pipe;
425 if (Setjmp( cnftalk.errjmp ))
426 return False; /* may memleak */
427 return getDeps();
430 static void
431 addServers( char **srv, int bType )
433 char *name, *class2;
434 const char *dtx, *cls;
435 struct display *d;
437 for (; *srv; srv++) {
438 if ((cls = strchr( *srv, '_' ))) {
439 if (!strNDup( &name, *srv, cls - *srv ))
440 return;
441 if (!strDup( &class2, cls )) {
442 free( name );
443 return;
445 } else {
446 if (!strDup( &name, *srv ))
447 return;
448 class2 = 0;
450 if ((d = findDisplayByName( name ))) {
451 if (d->class2)
452 free( d->class2 );
453 dtx = "existing";
454 } else {
455 if (!(d = newDisplay( name ))) {
456 free( name );
457 if (class2)
458 free( class2 );
459 return;
461 dtx = "new";
463 d->stillThere = True;
464 d->class2 = class2;
465 d->displayType = (*name == ':' ? dLocal : dForeign) | bType;
466 if ((bType & d_lifetime) == dReserve) {
467 if (d->status == notRunning)
468 d->status = reserve;
469 } else {
470 if (d->status == reserve)
471 d->status = notRunning;
473 debug( "found %s %s%s display: %s %s\n", dtx,
474 ((d->displayType & d_location) == dLocal) ? "local" : "foreign",
475 ((d->displayType & d_lifetime) == dReserve) ? " reserve" : "",
476 d->name, d->class2 );
477 free( name );
481 void
482 scanServers( void )
484 debug( "scanServers\n" );
485 addServers( staticServers, dFromFile | dPermanent );
486 addServers( reserveServers, dFromFile | dReserve );