~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kdm/kfrontend/kdm_config.c

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Read options from kdmrc
 
4
 
 
5
Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
 
6
 
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 2 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program; if not, write to the Free Software
 
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
21
 
 
22
*/
 
23
 
 
24
#include <config-workspace.h>
 
25
 
 
26
#include <stdio.h>
 
27
#include <unistd.h>
 
28
#include <stdarg.h>
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
#include <fcntl.h>
 
32
#include <ctype.h>
 
33
#include <errno.h>
 
34
#include <netdb.h>
 
35
#include <netinet/in.h>
 
36
#include <grp.h>
 
37
#ifdef _POSIX_PRIORITY_SCHEDULING
 
38
# include <sched.h>
 
39
#endif
 
40
 
 
41
#include <X11/X.h>
 
42
#ifdef FamilyInternet6
 
43
# define IPv6
 
44
#endif
 
45
 
 
46
#include <greet.h>
 
47
 
 
48
#define WANT_CONF_READ
 
49
#include <config.ci>
 
50
 
 
51
/*
 
52
 * Section/Entry definition structs
 
53
 */
 
54
 
 
55
typedef struct Ent {
 
56
    const char *name;
 
57
    int id;
 
58
    void *ptr;
 
59
    const char *def;
 
60
} Ent;
 
61
 
 
62
typedef struct Sect {
 
63
    const char *name;
 
64
    Ent *ents;
 
65
    int numents;
 
66
} Sect;
 
67
 
 
68
/*
 
69
 * Parsed ini file structs
 
70
 */
 
71
 
 
72
typedef struct Entry {
 
73
    struct Entry *next;
 
74
    const char *val;
 
75
    Ent *ent;
 
76
    int vallen;
 
77
    int line;
 
78
} Entry;
 
79
 
 
80
typedef struct Section {
 
81
    struct Section *next;
 
82
    Entry *entries;
 
83
    Sect *sect;
 
84
    const char *name, *dname, *dhost, *dnum, *dclass;
 
85
    int nlen, dlen, dhostl, dnuml, dclassl;
 
86
} Section;
 
87
 
 
88
 
 
89
/*
 
90
 * Split up display-name/-class for fast comparison
 
91
 */
 
92
typedef struct DSpec {
 
93
    const char *dhost, *dnum, *dclass;
 
94
    int dhostl, dnuml, dclassl;
 
95
} DSpec;
 
96
 
 
97
 
 
98
/*
 
99
 * Config value storage structures
 
100
 */
 
101
 
 
102
typedef union Value {
 
103
    struct {
 
104
        const char *ptr;
 
105
        int len; /* including 0-terminator */
 
106
    } str;
 
107
    struct {
 
108
        union Value *ptr;
 
109
        int totlen; /* summed up length of all contained strings */
 
110
    } argv;
 
111
    int num;
 
112
} Value;
 
113
 
 
114
typedef struct Val {
 
115
    Value val;
 
116
    int id;
 
117
} Val;
 
118
 
 
119
typedef struct ValArr {
 
120
    Val *ents;
 
121
    int nents, esiz, nchars, nptrs;
 
122
} ValArr;
 
123
 
 
124
 
 
125
static void *Malloc(size_t size);
 
126
static void *Realloc(void *ptr, size_t size);
 
127
 
 
128
#define PRINT_QUOTES
 
129
#define LOG_NAME "kdm_config"
 
130
#define LOG_DEBUG_MASK DEBUG_CONFIG
 
131
#define LOG_PANIC_EXIT 1
 
132
#define STATIC static
 
133
#include <printf.c>
 
134
 
 
135
 
 
136
static void *
 
137
Malloc(size_t size)
 
138
{
 
139
    void *ret;
 
140
 
 
141
    if (!(ret = malloc(size)))
 
142
        logOutOfMem();
 
143
    return ret;
 
144
}
 
145
 
 
146
static void *
 
147
Realloc(void *ptr, size_t size)
 
148
{
 
149
    void *ret;
 
150
 
 
151
    if (!(ret = realloc(ptr, size)) && size)
 
152
        logOutOfMem();
 
153
    return ret;
 
154
}
 
155
 
 
156
 
 
157
static void
 
158
mkDSpec(DSpec *spec, const char *dname, const char *dclass)
 
159
{
 
160
    spec->dhost = dname;
 
161
    for (spec->dhostl = 0; dname[spec->dhostl] != ':'; spec->dhostl++);
 
162
    spec->dnum = dname + spec->dhostl + 1;
 
163
    spec->dnuml = strlen(spec->dnum);
 
164
    spec->dclass = dclass;
 
165
    spec->dclassl = strlen(dclass);
 
166
}
 
167
 
 
168
 
 
169
static int rfd, wfd;
 
170
 
 
171
static int
 
172
reader(void *buf, int count)
 
173
{
 
174
    int ret, rlen;
 
175
 
 
176
    for (rlen = 0; rlen < count;) {
 
177
      dord:
 
178
        ret = read(rfd, (char *)buf + rlen, count - rlen);
 
179
        if (ret < 0) {
 
180
            if (errno == EINTR)
 
181
                goto dord;
 
182
            if (errno == EAGAIN)
 
183
                break;
 
184
            return -1;
 
185
        }
 
186
        if (!ret)
 
187
            break;
 
188
        rlen += ret;
 
189
    }
 
190
    return rlen;
 
191
}
 
192
 
 
193
static void
 
194
gRead(void *buf, int count)
 
195
{
 
196
    if (reader(buf, count) != count)
 
197
        logPanic("Cannot read from core\n");
 
198
}
 
199
 
 
200
static void
 
201
gWrite(const void *buf, int count)
 
202
{
 
203
    if (write(wfd, buf, count) != count)
 
204
        logPanic("Cannot write to core\n");
 
205
#ifdef _POSIX_PRIORITY_SCHEDULING
 
206
    if ((debugLevel & DEBUG_HLPCON))
 
207
        sched_yield();
 
208
#endif
 
209
}
 
210
 
 
211
static void
 
212
gSendInt(int val)
 
213
{
 
214
    gWrite(&val, sizeof(val));
 
215
}
 
216
 
 
217
static void
 
218
gSendStr(const char *buf)
 
219
{
 
220
    if (buf) {
 
221
        int len = strlen(buf) + 1;
 
222
        gWrite(&len, sizeof(len));
 
223
        gWrite(buf, len);
 
224
    } else {
 
225
        gWrite(&buf, sizeof(int));
 
226
    }
 
227
}
 
228
 
 
229
static void
 
230
gSendNStr(const char *buf, int len)
 
231
{
 
232
    int tlen = len + 1;
 
233
    gWrite(&tlen, sizeof(tlen));
 
234
    gWrite(buf, len);
 
235
    gWrite("", 1);
 
236
}
 
237
 
 
238
#ifdef XDMCP
 
239
static void
 
240
gSendArr(int len, const char *data)
 
241
{
 
242
    gWrite(&len, sizeof(len));
 
243
    gWrite(data, len);
 
244
}
 
245
#endif
 
246
 
 
247
static int
 
248
gRecvCmd(int *val)
 
249
{
 
250
    if (reader(val, sizeof(*val)) != sizeof(*val))
 
251
        return False;
 
252
    return True;
 
253
}
 
254
 
 
255
static int
 
256
gRecvInt()
 
257
{
 
258
    int val;
 
259
 
 
260
    gRead(&val, sizeof(val));
 
261
    return val;
 
262
}
 
263
 
 
264
static char *
 
265
gRecvStr()
 
266
{
 
267
    int len;
 
268
    char *buf;
 
269
 
 
270
    len = gRecvInt();
 
271
    if (!len)
 
272
        return 0;
 
273
    if (!(buf = malloc(len)))
 
274
        logPanic("No memory for read buffer");
 
275
    gRead(buf, len);
 
276
    return buf;
 
277
}
 
278
 
 
279
 
 
280
/* #define WANT_CLOSE 1 */
 
281
 
 
282
typedef struct File {
 
283
    char *buf, *eof, *cur;
 
284
#if defined(HAVE_MMAP) && defined(WANT_CLOSE)
 
285
    int ismapped;
 
286
#endif
 
287
} File;
 
288
 
 
289
static int
 
290
readFile(File *file, const char *fn, const char *what)
 
291
{
 
292
    int fd;
 
293
    off_t flen;
 
294
 
 
295
    if ((fd = open(fn, O_RDONLY)) < 0) {
 
296
        logInfo("Cannot open %s file %s\n", what, fn);
 
297
        return False;
 
298
    }
 
299
 
 
300
    flen = lseek(fd, 0, SEEK_END);
 
301
#ifdef HAVE_MMAP
 
302
# ifdef WANT_CLOSE
 
303
    file->ismapped = False;
 
304
# endif
 
305
    file->buf = mmap(0, flen + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 
306
# ifdef WANT_CLOSE
 
307
    if (file->buf)
 
308
        file->ismapped = True;
 
309
    else
 
310
# else
 
311
    if (!file->buf)
 
312
# endif
 
313
#endif
 
314
    {
 
315
        if (!(file->buf = Malloc(flen + 1))) {
 
316
            close(fd);
 
317
            return False;
 
318
        }
 
319
        lseek(fd, 0, SEEK_SET);
 
320
        if (read(fd, file->buf, flen) != flen) {
 
321
            free(file->buf);
 
322
            logError("Cannot read %s file %s\n", what, fn);
 
323
            close(fd);
 
324
            return False;
 
325
        }
 
326
    }
 
327
    file->eof = (file->cur = file->buf) + flen;
 
328
    close(fd);
 
329
    return True;
 
330
}
 
331
 
 
332
#ifdef WANT_CLOSE
 
333
static void
 
334
freeBuf(File *file)
 
335
{
 
336
# ifdef HAVE_MMAP
 
337
    if (file->ismapped)
 
338
        munmap(file->buf, file->eof - file->buf + 1);
 
339
    else
 
340
# endif
 
341
        free(file->buf);
 
342
}
 
343
#endif
 
344
 
 
345
CONF_READ_VARS
 
346
 
 
347
#define C_MTYPE_MASK  0x30000000
 
348
# define C_PATH          0x10000000     /* C_TYPE_STR is a path spec */
 
349
# define C_BOOL          0x10000000     /* C_TYPE_INT is a boolean */
 
350
# define C_ENUM          0x20000000     /* C_TYPE_INT is an enum (option) */
 
351
# define C_GRP           0x30000000     /* C_TYPE_INT is a group spec */
 
352
#define C_INTERNAL    0x40000000        /* don't expose to core */
 
353
#define C_CONFIG      0x80000000        /* process only for finding deps */
 
354
 
 
355
#ifdef XDMCP
 
356
static int
 
357
PrequestPort(Value *retval)
 
358
{
 
359
    if (!VxdmcpEnable.num) {
 
360
        retval->num = 0;
 
361
        return True;
 
362
    }
 
363
    return False;
 
364
}
 
365
#endif
 
366
 
 
367
static Value
 
368
    emptyStr = { { "", 1 } },
 
369
    nullValue = { { 0, 0 } },
 
370
    emptyArgv = { { (char *)&nullValue, 0 } };
 
371
 
 
372
static int
 
373
PnoPassUsers(Value *retval)
 
374
{
 
375
    if (!VnoPassEnable.num) {
 
376
        *retval = emptyArgv;
 
377
        return True;
 
378
    }
 
379
    return False;
 
380
}
 
381
 
 
382
static int
 
383
PautoLoginX(Value *retval)
 
384
{
 
385
    if (!VautoLoginEnable.num) {
 
386
        *retval = emptyStr;
 
387
        return True;
 
388
    }
 
389
    return False;
 
390
}
 
391
 
 
392
CONF_READ_ENTRIES
 
393
 
 
394
static const char *kdmrc = KDMCONF "/kdmrc";
 
395
 
 
396
static Section *rootsec;
 
397
 
 
398
static void
 
399
readConfig()
 
400
{
 
401
    const char *nstr, *dstr, *cstr, *dhost, *dnum, *dclass;
 
402
    char *s, *e, *st, *en, *ek, *sl, *pt;
 
403
    Section *cursec;
 
404
    Entry *curent;
 
405
    Ent *ce;
 
406
    int nlen, dlen, clen, dhostl, dnuml, dclassl;
 
407
    int i, line, sectmoan, restl;
 
408
    File file;
 
409
    static int confread;
 
410
 
 
411
    if (confread)
 
412
        return;
 
413
    confread = True;
 
414
 
 
415
    debug("reading config %s ...\n", kdmrc);
 
416
    if (!readFile(&file, kdmrc, "master configuration"))
 
417
        return;
 
418
 
 
419
    for (s = file.buf, line = 0, cursec = 0, sectmoan = 1; s < file.eof; s++) {
 
420
        line++;
 
421
 
 
422
        while ((s < file.eof) && isspace(*s) && (*s != '\n'))
 
423
            s++;
 
424
 
 
425
        if ((s < file.eof) && ((*s == '\n') || (*s == '#'))) {
 
426
          sktoeol:
 
427
            while ((s < file.eof) && (*s != '\n'))
 
428
                s++;
 
429
            continue;
 
430
        }
 
431
        sl = s;
 
432
 
 
433
        if (*s == '[') {
 
434
            sectmoan = False;
 
435
            while ((s < file.eof) && (*s != '\n'))
 
436
                s++;
 
437
            e = s - 1;
 
438
            while ((e > sl) && isspace(*e))
 
439
                e--;
 
440
            if (*e != ']') {
 
441
                cursec = 0;
 
442
                logError("Invalid section header at %s:%d\n", kdmrc, line);
 
443
                continue;
 
444
            }
 
445
            nstr = sl + 1;
 
446
            nlen = e - nstr;
 
447
            for (cursec = rootsec; cursec; cursec = cursec->next)
 
448
                if (nlen == cursec->nlen &&
 
449
                    !memcmp(nstr, cursec->name, nlen))
 
450
                {
 
451
                    logInfo("Multiple occurrences of section [%.*s] in %s. "
 
452
                            "Consider merging them.\n", nlen, nstr, kdmrc);
 
453
                    goto secfnd;
 
454
                }
 
455
            if (nstr[0] == 'X' && nstr[1] == '-') {
 
456
                cstr = nstr + nlen;
 
457
                clen = 0;
 
458
                while (++clen, *--cstr != '-');
 
459
                if (cstr == nstr + 1)
 
460
                    goto illsec;
 
461
                dstr = nstr + 2;
 
462
                dlen = nlen - clen - 2;
 
463
                dhost = dstr;
 
464
                dhostl = 0;
 
465
                for (restl = dlen; restl; restl--) {
 
466
                    if (dhost[dhostl] == ':') {
 
467
                        dnum = dhost + dhostl + 1;
 
468
                        dnuml = 0;
 
469
                        for (restl--; restl; restl--) {
 
470
                            if (dnum[dnuml] == '_') {
 
471
                                dclass = dnum + dnuml + 1;
 
472
                                dclassl = restl;
 
473
                                goto gotall;
 
474
                            }
 
475
                            dnuml++;
 
476
                        }
 
477
                        goto gotnum;
 
478
                    }
 
479
                    dhostl++;
 
480
                }
 
481
                dnum = "*";
 
482
                dnuml = 1;
 
483
              gotnum:
 
484
                dclass = "*";
 
485
                dclassl = 1;
 
486
              gotall: ;
 
487
            } else {
 
488
                if (nstr[0] == '-')
 
489
                    goto illsec;
 
490
                dstr = 0;
 
491
                dlen = 0;
 
492
                dhost = 0;
 
493
                dhostl = 0;
 
494
                dnum = 0;
 
495
                dnuml = 0;
 
496
                dclass = 0;
 
497
                dclassl = 0;
 
498
                cstr = nstr;
 
499
                clen = nlen;
 
500
            }
 
501
            for (i = 0; i < as(allSects); i++)
 
502
                if ((int)strlen(allSects[i]->name) == clen &&
 
503
                        !memcmp(allSects[i]->name, cstr, clen))
 
504
                    goto newsec;
 
505
          illsec:
 
506
            cursec = 0;
 
507
            logError("Unrecognized section name [%.*s] at %s:%d\n",
 
508
                     nlen, nstr, kdmrc, line);
 
509
            continue;
 
510
          newsec:
 
511
            if (!(cursec = Malloc(sizeof(*cursec))))
 
512
                return;
 
513
            cursec->name = nstr;
 
514
            cursec->nlen = nlen;
 
515
            cursec->dname = dstr;
 
516
            cursec->dlen = dlen;
 
517
            cursec->dhost = dhost;
 
518
            cursec->dhostl = dhostl;
 
519
            cursec->dnum = dnum;
 
520
            cursec->dnuml = dnuml;
 
521
            cursec->dclass = dclass;
 
522
            cursec->dclassl = dclassl;
 
523
            cursec->sect = allSects[i];
 
524
            cursec->entries = 0;
 
525
            cursec->next = rootsec;
 
526
            rootsec = cursec;
 
527
            /*debug("now in section [%.*s], dpy '%.*s', core '%.*s'\n",
 
528
                   nlen, nstr, dlen, dstr, clen, cstr);*/
 
529
          secfnd:
 
530
            continue;
 
531
        }
 
532
 
 
533
        if (!cursec) {
 
534
            if (sectmoan) {
 
535
                sectmoan = False;
 
536
                logError("Entry outside any section at %s:%d", kdmrc, line);
 
537
            }
 
538
            goto sktoeol;
 
539
        }
 
540
 
 
541
        for (; (s < file.eof) && (*s != '\n'); s++)
 
542
            if (*s == '=')
 
543
                goto haveeq;
 
544
        logError("Invalid entry (missing '=') at %s:%d\n", kdmrc, line);
 
545
        continue;
 
546
 
 
547
      haveeq:
 
548
        for (ek = s - 1; ; ek--) {
 
549
            if (ek < sl) {
 
550
                logError("Invalid entry (empty key) at %s:%d\n", kdmrc, line);
 
551
                goto sktoeol;
 
552
            }
 
553
            if (!isspace(*ek))
 
554
                break;
 
555
        }
 
556
 
 
557
        s++;
 
558
        while ((s < file.eof) && isspace(*s) && (*s != '\n'))
 
559
            s++;
 
560
        for (pt = st = en = s; s < file.eof && *s != '\n'; s++) {
 
561
            if (*s == '\\') {
 
562
                s++;
 
563
                if (s >= file.eof || *s == '\n') {
 
564
                    logError("Trailing backslash at %s:%d\n", kdmrc, line);
 
565
                    break;
 
566
                }
 
567
                switch (*s) {
 
568
                case 's': *pt++ = ' '; break;
 
569
                case 't': *pt++ = '\t'; break;
 
570
                case 'n': *pt++ = '\n'; break;
 
571
                case 'r': *pt++ = '\r'; break;
 
572
                case '\\': *pt++ = '\\'; break;
 
573
                default: *pt++ = '\\'; *pt++ = *s; break;
 
574
                }
 
575
                en = pt;
 
576
            } else {
 
577
                *pt++ = *s;
 
578
                if (*s != ' ' && *s != '\t')
 
579
                    en = pt;
 
580
            }
 
581
        }
 
582
 
 
583
        nstr = sl;
 
584
        nlen = ek - sl + 1;
 
585
        /*debug("read entry '%.*s'='%.*s'\n", nlen, nstr, en - st, st);*/
 
586
        for (i = 0; i < cursec->sect->numents; i++) {
 
587
            ce = cursec->sect->ents + i;
 
588
            if ((int)strlen(ce->name) == nlen &&
 
589
                    !memcmp(ce->name, nstr, nlen))
 
590
                goto keyok;
 
591
        }
 
592
        logError("Unrecognized key '%.*s' in section [%.*s] at %s:%d\n",
 
593
                 nlen, nstr, cursec->nlen, cursec->name, kdmrc, line);
 
594
        continue;
 
595
      keyok:
 
596
        for (curent = cursec->entries; curent; curent = curent->next)
 
597
            if (ce == curent->ent) {
 
598
                logError("Multiple occurrences of key '%s' in section [%.*s] of %s\n",
 
599
                         ce->name, cursec->nlen, cursec->name, kdmrc);
 
600
                goto keyfnd;
 
601
            }
 
602
        if (!(curent = Malloc(sizeof(*curent))))
 
603
            return;
 
604
        curent->ent = ce;
 
605
        curent->line = line;
 
606
        curent->val = st;
 
607
        curent->vallen = en - st;
 
608
        curent->next = cursec->entries;
 
609
        cursec->entries = curent;
 
610
      keyfnd:
 
611
        continue;
 
612
    }
 
613
}
 
614
 
 
615
static Entry *
 
616
findGEnt(int id)
 
617
{
 
618
    Section *cursec;
 
619
    Entry *curent;
 
620
 
 
621
    for (cursec = rootsec; cursec; cursec = cursec->next)
 
622
        if (!cursec->dname)
 
623
            for (curent = cursec->entries; curent; curent = curent->next)
 
624
                if (curent->ent->id == id) {
 
625
                    debug("line %d: %s = %'.*s\n",
 
626
                          curent->line, curent->ent->name,
 
627
                          curent->vallen, curent->val);
 
628
                    return curent;
 
629
                }
 
630
    return 0;
 
631
}
 
632
 
 
633
/* Display name match scoring:
 
634
 * - class (any/exact) -> 0/1
 
635
 * - number (any/exact) -> 0/2
 
636
 * - host (any/nonempty/trail/exact) -> 0/4/8/12
 
637
 */
 
638
static Entry *
 
639
findDEnt(int id, DSpec *dspec)
 
640
{
 
641
    Section *cursec, *bestsec = 0;
 
642
    Entry *curent, *bestent;
 
643
    int score, bestscore;
 
644
 
 
645
    bestscore = -1, bestent = 0;
 
646
    for (cursec = rootsec; cursec; cursec = cursec->next)
 
647
        if (cursec->dname) {
 
648
            score = 0;
 
649
            if (cursec->dclassl != 1 || cursec->dclass[0] != '*') {
 
650
                if (cursec->dclassl == dspec->dclassl &&
 
651
                        !memcmp(cursec->dclass, dspec->dclass, dspec->dclassl))
 
652
                    score = 1;
 
653
                else
 
654
                    continue;
 
655
            }
 
656
            if (cursec->dnuml != 1 || cursec->dnum[0] != '*') {
 
657
                if (cursec->dnuml == dspec->dnuml &&
 
658
                        !memcmp(cursec->dnum, dspec->dnum, dspec->dnuml))
 
659
                    score += 2;
 
660
                else
 
661
                    continue;
 
662
            }
 
663
            if (cursec->dhostl != 1 || cursec->dhost[0] != '*') {
 
664
                if (cursec->dhostl == 1 && cursec->dhost[0] == '+') {
 
665
                    if (dspec->dhostl)
 
666
                        score += 4;
 
667
                    else
 
668
                        continue;
 
669
                } else if (cursec->dhost[0] == '.') {
 
670
                    if (cursec->dhostl < dspec->dhostl &&
 
671
                        !memcmp(cursec->dhost,
 
672
                                dspec->dhost + dspec->dhostl - cursec->dhostl,
 
673
                                cursec->dhostl))
 
674
                        score += 8;
 
675
                    else
 
676
                        continue;
 
677
                } else {
 
678
                    if (cursec->dhostl == dspec->dhostl &&
 
679
                            !memcmp(cursec->dhost, dspec->dhost, dspec->dhostl))
 
680
                        score += 12;
 
681
                    else
 
682
                        continue;
 
683
                }
 
684
            }
 
685
            if (score > bestscore) {
 
686
                for (curent = cursec->entries; curent; curent = curent->next)
 
687
                    if (curent->ent->id == id) {
 
688
                        bestent = curent;
 
689
                        bestsec = cursec;
 
690
                        bestscore = score;
 
691
                        break;
 
692
                    }
 
693
            }
 
694
        }
 
695
    if (bestent)
 
696
        debug("line %d: %.*s:%.*s_%.*s/%s = %'.*s\n", bestent->line,
 
697
              bestsec->dhostl, bestsec->dhost,
 
698
              bestsec->dnuml, bestsec->dnum,
 
699
              bestsec->dclassl, bestsec->dclass,
 
700
              bestent->ent->name, bestent->vallen, bestent->val);
 
701
    return bestent;
 
702
}
 
703
 
 
704
static const char *
 
705
convertValue(Ent *et, Value *retval, int vallen, const char *val, char **eopts)
 
706
{
 
707
    Value *ents;
 
708
    int i, b, e, tlen, nents, esiz;
 
709
    char buf[80];
 
710
 
 
711
    switch (et->id & C_TYPE_MASK) {
 
712
    case C_TYPE_INT:
 
713
        for (i = 0; i < vallen && i < (int)sizeof(buf) - 1; i++)
 
714
            buf[i] = tolower(val[i]);
 
715
        buf[i] = 0;
 
716
        if ((et->id & C_MTYPE_MASK) == C_BOOL) {
 
717
            if (!strcmp(buf, "true") ||
 
718
                !strcmp(buf, "on") ||
 
719
                !strcmp(buf, "yes") ||
 
720
                !strcmp(buf, "1"))
 
721
                retval->num = 1;
 
722
            else if (!strcmp(buf, "false") ||
 
723
                     !strcmp(buf, "off") ||
 
724
                     !strcmp(buf, "no") ||
 
725
                     !strcmp(buf, "0"))
 
726
                retval->num = 0;
 
727
            else
 
728
                return "boolean";
 
729
            return 0;
 
730
        } else if ((et->id & C_MTYPE_MASK) == C_ENUM) {
 
731
            for (i = 0; eopts[i]; i++)
 
732
                if (!memcmp(eopts[i], val, vallen) && !eopts[i][vallen]) {
 
733
                    retval->num = i;
 
734
                    return 0;
 
735
                }
 
736
            return "option";
 
737
        } else if ((et->id & C_MTYPE_MASK) == C_GRP) {
 
738
            struct group *ge;
 
739
            if ((ge = getgrnam(buf))) {
 
740
                retval->num = ge->gr_gid;
 
741
                return 0;
 
742
            }
 
743
        }
 
744
        if (sscanf(buf, "%i", &retval->num) != 1)
 
745
            return "integer";
 
746
        return 0;
 
747
    case C_TYPE_STR:
 
748
        retval->str.ptr = val;
 
749
        retval->str.len = vallen + 1;
 
750
        if ((et->id & C_MTYPE_MASK) == C_PATH)
 
751
            if (vallen && val[vallen-1] == '/')
 
752
                retval->str.len--;
 
753
        return 0;
 
754
    case C_TYPE_ARGV:
 
755
        if (!(ents = Malloc(sizeof(Value) * (esiz = 10))))
 
756
            return 0;
 
757
        for (nents = 0, tlen = 0, i = 0; ; i++) {
 
758
            for (; i < vallen && isspace(val[i]); i++) ;
 
759
            for (b = i; i < vallen && val[i] != ','; i++) ;
 
760
            if (b == i)
 
761
                break;
 
762
            for (e = i; e > b && isspace(val[e - 1]); e--) ;
 
763
            if (esiz < nents + 2) {
 
764
                Value *entsn = Realloc(ents, sizeof(Value) * (esiz = esiz * 2 + 1));
 
765
                if (!nents)
 
766
                    break;
 
767
                ents = entsn;
 
768
            }
 
769
            ents[nents].str.ptr = val + b;
 
770
            ents[nents].str.len = e - b;
 
771
            nents++;
 
772
            tlen += e - b + 1;
 
773
        }
 
774
        ents[nents].str.ptr = 0;
 
775
        retval->argv.ptr = ents;
 
776
        retval->argv.totlen = tlen;
 
777
        return 0;
 
778
    default:
 
779
        logError("Internal error: unknown value type in id %#x\n", et->id);
 
780
        return 0;
 
781
    }
 
782
}
 
783
 
 
784
static void
 
785
getValue(Ent *et, DSpec *dspec, Value *retval, char **eopts)
 
786
{
 
787
    Entry *ent;
 
788
    const char *errs;
 
789
 
 
790
/*    debug("Getting value %#x\n", et->id);*/
 
791
    if (dspec)
 
792
        ent = findDEnt(et->id, dspec);
 
793
    else
 
794
        ent = findGEnt(et->id);
 
795
    if (ent) {
 
796
        if (!(errs = convertValue(et, retval, ent->vallen, ent->val, eopts)))
 
797
            return;
 
798
        logError("Invalid %s value '%.*s' at %s:%d\n",
 
799
                 errs, ent->vallen, ent->val, kdmrc, ent->line);
 
800
    }
 
801
    debug("default: %s = %'s\n", et->name, et->def);
 
802
    if ((errs = convertValue(et, retval, strlen(et->def), et->def, eopts)))
 
803
        logError("Internal error: invalid default %s value '%s' for key %s\n",
 
804
                 errs, et->def, et->name);
 
805
}
 
806
 
 
807
static int
 
808
addValue(ValArr *va, int id, Value *val)
 
809
{
 
810
    int nu;
 
811
 
 
812
/*    debug("Addig value %#x\n", id);*/
 
813
    if (va->nents == va->esiz) {
 
814
        va->ents = Realloc(va->ents, sizeof(Val) * (va->esiz += 50));
 
815
        if (!va->ents)
 
816
            return False;
 
817
    }
 
818
    va->ents[va->nents].id = id;
 
819
    va->ents[va->nents].val = *val;
 
820
    va->nents++;
 
821
    switch (id & C_TYPE_MASK) {
 
822
    case C_TYPE_INT:
 
823
        break;
 
824
    case C_TYPE_STR:
 
825
        va->nchars += val->str.len;
 
826
        break;
 
827
    case C_TYPE_ARGV:
 
828
        va->nchars += val->argv.totlen;
 
829
        for (nu = 0; val->argv.ptr[nu++].str.ptr;);
 
830
        va->nptrs += nu;
 
831
        break;
 
832
    }
 
833
    return True;
 
834
}
 
835
 
 
836
static void
 
837
copyValues(ValArr *va, Sect *sec, DSpec *dspec, int isconfig)
 
838
{
 
839
    Value val;
 
840
    int i;
 
841
 
 
842
    debug("getting values for section class [%s]\n", sec->name);
 
843
    for (i = 0; i < sec->numents; i++) {
 
844
/*debug ("value %#x\n", sec->ents[i].id);*/
 
845
        if ((sec->ents[i].id & (int)C_CONFIG) != isconfig) {
 
846
        } else if (sec->ents[i].id & C_INTERNAL) {
 
847
            getValue(sec->ents + i, dspec, ((Value *)sec->ents[i].ptr), 0);
 
848
        } else {
 
849
            if (((sec->ents[i].id & C_MTYPE_MASK) == C_ENUM) ||
 
850
                !sec->ents[i].ptr ||
 
851
                !((int (*)(Value *))sec->ents[i].ptr)(&val))
 
852
            {
 
853
                getValue(sec->ents + i, dspec, &val,
 
854
                         (char **)sec->ents[i].ptr);
 
855
            }
 
856
            if (!addValue(va, sec->ents[i].id, &val))
 
857
                break;
 
858
        }
 
859
    }
 
860
    return;
 
861
}
 
862
 
 
863
static void
 
864
sendValues(ValArr *va)
 
865
{
 
866
    Value *cst;
 
867
    int i, nu;
 
868
 
 
869
    gSendInt(va->nents);
 
870
    gSendInt(va->nptrs);
 
871
    gSendInt(0/*va->nints*/);
 
872
    gSendInt(va->nchars);
 
873
    for (i = 0; i < va->nents; i++) {
 
874
        gSendInt(va->ents[i].id & ~C_PRIVATE);
 
875
        switch (va->ents[i].id & C_TYPE_MASK) {
 
876
        case C_TYPE_INT:
 
877
            gSendInt(va->ents[i].val.num);
 
878
            break;
 
879
        case C_TYPE_STR:
 
880
            gSendNStr(va->ents[i].val.str.ptr, va->ents[i].val.str.len - 1);
 
881
            break;
 
882
        case C_TYPE_ARGV:
 
883
            cst = va->ents[i].val.argv.ptr;
 
884
            for (nu = 0; cst[nu].str.ptr; nu++);
 
885
            gSendInt(nu);
 
886
            for (; cst->str.ptr; cst++)
 
887
                gSendNStr(cst->str.ptr, cst->str.len);
 
888
            break;
 
889
        }
 
890
    }
 
891
}
 
892
 
 
893
 
 
894
#ifdef XDMCP
 
895
static char *
 
896
readWord(File *file, int *len, int EOFatEOL)
 
897
{
 
898
    char *wordp, *wordBuffer;
 
899
    int quoted;
 
900
    char c;
 
901
 
 
902
  rest:
 
903
    wordp = wordBuffer = file->cur;
 
904
  mloop:
 
905
    quoted = False;
 
906
  qloop:
 
907
    if (file->cur == file->eof) {
 
908
      doeow:
 
909
        if (wordp == wordBuffer)
 
910
            return 0;
 
911
      retw:
 
912
        *wordp = '\0';
 
913
        *len = wordp - wordBuffer;
 
914
        return wordBuffer;
 
915
    }
 
916
    c = *file->cur++;
 
917
    switch (c) {
 
918
    case '#':
 
919
        if (quoted)
 
920
            break;
 
921
        do {
 
922
            if (file->cur == file->eof)
 
923
                goto doeow;
 
924
            c = *file->cur++;
 
925
        } while (c != '\n');
 
926
    case '\0':
 
927
    case '\n':
 
928
        if (EOFatEOL && !quoted) {
 
929
            file->cur--;
 
930
            goto doeow;
 
931
        }
 
932
        if (wordp != wordBuffer) {
 
933
            file->cur--;
 
934
            goto retw;
 
935
        }
 
936
        goto rest;
 
937
    case ' ':
 
938
    case '\t':
 
939
        if (wordp != wordBuffer)
 
940
            goto retw;
 
941
        goto rest;
 
942
    case '\\':
 
943
        if (!quoted) {
 
944
            quoted = True;
 
945
            goto qloop;
 
946
        }
 
947
        break;
 
948
    }
 
949
    *wordp++ = c;
 
950
    goto mloop;
 
951
}
 
952
 
 
953
#define ALIAS_CHARACTER     '%'
 
954
#define EQUAL_CHARACTER     '='
 
955
#define NEGATE_CHARACTER    '!'
 
956
#define CHOOSER_STRING      "CHOOSER"
 
957
#define BROADCAST_STRING    "BROADCAST"
 
958
#define NOBROADCAST_STRING  "NOBROADCAST"
 
959
#define LISTEN_STRING       "LISTEN"
 
960
#define WILDCARD_STRING     "*"
 
961
 
 
962
typedef struct _HostEntry {
 
963
    struct _HostEntry *next;
 
964
    int type;
 
965
    union _hostOrAlias {
 
966
        char *aliasPattern;
 
967
        char *hostPattern;
 
968
        struct _display {
 
969
            int connectionType;
 
970
            int hostAddrLen;
 
971
            char *hostAddress;
 
972
        } displayAddress;
 
973
    } entry;
 
974
} HostEntry;
 
975
 
 
976
typedef struct _ListenEntry {
 
977
    struct _ListenEntry *next;
 
978
    int iface;
 
979
    int mcasts;
 
980
    int nmcasts;
 
981
} ListenEntry;
 
982
 
 
983
typedef struct _AliasEntry {
 
984
    struct _AliasEntry *next;
 
985
    char *name;
 
986
    HostEntry **pHosts;
 
987
    int hosts;
 
988
    int nhosts;
 
989
    int hasBad;
 
990
} AliasEntry;
 
991
 
 
992
typedef struct _AclEntry {
 
993
    struct _AclEntry *next;
 
994
    HostEntry **pEntries;
 
995
    int entries;
 
996
    int nentries;
 
997
    HostEntry **pHosts;
 
998
    int hosts;
 
999
    int nhosts;
 
1000
    int flags;
 
1001
} AclEntry;
 
1002
 
 
1003
 
 
1004
static int
 
1005
hasGlobCharacters(char *s)
 
1006
{
 
1007
    for (;;)
 
1008
        switch (*s++) {
 
1009
        case '?':
 
1010
        case '*':
 
1011
            return True;
 
1012
        case '\0':
 
1013
            return False;
 
1014
        }
 
1015
}
 
1016
 
 
1017
#define PARSE_ALL       0
 
1018
#define PARSE_NO_BCAST  1
 
1019
#define PARSE_NO_PAT    2
 
1020
#define PARSE_NO_ALIAS  4
 
1021
 
 
1022
static int
 
1023
parseHost(int *nHosts, HostEntry ***hostPtr, int *nChars,
 
1024
          char *hostOrAlias, int len, int parse)
 
1025
{
 
1026
#if defined(IPv6) && defined(AF_INET6)
 
1027
    struct addrinfo *ai;
 
1028
#else
 
1029
    struct hostent *hostent;
 
1030
#endif
 
1031
    void *addr;
 
1032
    int addr_type, addr_len;
 
1033
 
 
1034
    if (!(**hostPtr = Malloc(sizeof(HostEntry))))
 
1035
        return False;
 
1036
    if (!(parse & PARSE_NO_BCAST) && !strcmp(hostOrAlias, BROADCAST_STRING)) {
 
1037
        (**hostPtr)->type = HOST_BROADCAST;
 
1038
    } else if (!(parse & PARSE_NO_ALIAS) && *hostOrAlias == ALIAS_CHARACTER) {
 
1039
        (**hostPtr)->type = HOST_ALIAS;
 
1040
        (**hostPtr)->entry.aliasPattern = hostOrAlias + 1;
 
1041
        *nChars += len;
 
1042
    } else if (!(parse & PARSE_NO_PAT) && hasGlobCharacters(hostOrAlias)) {
 
1043
        (**hostPtr)->type = HOST_PATTERN;
 
1044
        (**hostPtr)->entry.hostPattern = hostOrAlias;
 
1045
        *nChars += len + 1;
 
1046
    } else {
 
1047
        (**hostPtr)->type = HOST_ADDRESS;
 
1048
#if defined(IPv6) && defined(AF_INET6)
 
1049
        if (getaddrinfo(hostOrAlias, 0, 0, &ai))
 
1050
#else
 
1051
        if (!(hostent = gethostbyname(hostOrAlias)))
 
1052
#endif
 
1053
        {
 
1054
            logWarn("XDMCP ACL: unresolved host %'s\n", hostOrAlias);
 
1055
            free(**hostPtr);
 
1056
            return False;
 
1057
        }
 
1058
#if defined(IPv6) && defined(AF_INET6)
 
1059
        addr_type = ai->ai_addr->sa_family;
 
1060
        if (ai->ai_family == AF_INET) {
 
1061
            addr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr;
 
1062
            addr_len = sizeof(struct in_addr);
 
1063
        } else /*if (ai->ai_addr->sa_family == AF_INET6)*/ {
 
1064
            addr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
 
1065
            addr_len = sizeof(struct in6_addr);
 
1066
        }
 
1067
#else
 
1068
        addr_type = hostent->h_addrtype;
 
1069
        addr = hostent->h_addr;
 
1070
        addr_len = hostent->h_length;
 
1071
#endif
 
1072
        if (!((**hostPtr)->entry.displayAddress.hostAddress =
 
1073
              Malloc(addr_len)))
 
1074
        {
 
1075
#if defined(IPv6) && defined(AF_INET6)
 
1076
            freeaddrinfo(ai);
 
1077
#endif
 
1078
            free(**hostPtr);
 
1079
            return False;
 
1080
        }
 
1081
        memcpy((**hostPtr)->entry.displayAddress.hostAddress, addr, addr_len);
 
1082
        *nChars += addr_len;
 
1083
        (**hostPtr)->entry.displayAddress.hostAddrLen = addr_len;
 
1084
        (**hostPtr)->entry.displayAddress.connectionType = addr_type;
 
1085
#if defined(IPv6) && defined(AF_INET6)
 
1086
        freeaddrinfo(ai);
 
1087
#endif
 
1088
    }
 
1089
    *hostPtr = &(**hostPtr)->next;
 
1090
    (*nHosts)++;
 
1091
    return True;
 
1092
}
 
1093
 
 
1094
/* Returns True if string is matched by pattern.  Does case folding. */
 
1095
static int
 
1096
patternMatch(const char *string, const char *pattern)
 
1097
{
 
1098
    int p, s;
 
1099
 
 
1100
    if (!string)
 
1101
        string = "";
 
1102
 
 
1103
    for (;;) {
 
1104
        s = *string++;
 
1105
        switch (p = *pattern++) {
 
1106
        case '*':
 
1107
            if (!*pattern)
 
1108
                return True;
 
1109
            for (string--; *string; string++)
 
1110
                if (patternMatch(string, pattern))
 
1111
                    return True;
 
1112
            return False;
 
1113
        case '?':
 
1114
            if (s == '\0')
 
1115
                return False;
 
1116
            break;
 
1117
        case '\0':
 
1118
            return s == '\0';
 
1119
        case '\\':
 
1120
            p = *pattern++;
 
1121
            /* fall through */
 
1122
        default:
 
1123
            if (tolower(p) != tolower(s))
 
1124
                return False;
 
1125
        }
 
1126
    }
 
1127
}
 
1128
 
 
1129
#define MAX_DEPTH     32
 
1130
 
 
1131
#define CHECK_NOT      1
 
1132
#define CHECK_NO_PAT   2
 
1133
 
 
1134
static int
 
1135
checkHostlist(HostEntry **hosts, int nh, AliasEntry *aliases, int na,
 
1136
              int depth, int flags)
 
1137
{
 
1138
    HostEntry *h;
 
1139
    AliasEntry *a;
 
1140
    int hn, an, am;
 
1141
 
 
1142
    for (h = *hosts, hn = 0; hn < nh; hn++, h = h->next)
 
1143
        if (h->type == HOST_ALIAS) {
 
1144
            if (depth == MAX_DEPTH) {
 
1145
                logError("XDMCP ACL: alias recursion involving %%%s\n",
 
1146
                         h->entry.aliasPattern);
 
1147
                return True;
 
1148
            }
 
1149
            for (a = aliases, an = 0, am = False; an < na; an++, a = a->next)
 
1150
                if (patternMatch(a->name, h->entry.aliasPattern)) {
 
1151
                    am = True;
 
1152
                    if ((flags & CHECK_NOT) && a->hasBad) {
 
1153
                        logError("XDMCP ACL: alias %%%s with unresolved hosts "
 
1154
                                 "in denying rule\n", a->name);
 
1155
                        return True;
 
1156
                    }
 
1157
                    if (checkHostlist(a->pHosts, a->nhosts, aliases, na,
 
1158
                                      depth + 1, flags))
 
1159
                        return True;
 
1160
                }
 
1161
            if (!am) {
 
1162
                if (flags & CHECK_NOT) {
 
1163
                    logError("XDMCP ACL: unresolved alias pattern %%%s "
 
1164
                             "in denying rule\n", h->entry.aliasPattern);
 
1165
                    return True;
 
1166
                } else
 
1167
                    logWarn("XDMCP ACL: unresolved alias pattern %%%s\n",
 
1168
                            h->entry.aliasPattern);
 
1169
            }
 
1170
        } else if (h->type == HOST_PATTERN && (flags & CHECK_NO_PAT)) {
 
1171
            logWarn("XDMCP ACL: wildcarded pattern %'s in host-only context\n",
 
1172
                    h->entry.hostPattern);
 
1173
        }
 
1174
    return False;
 
1175
}
 
1176
 
 
1177
static void
 
1178
readAccessFile(const char *fname)
 
1179
{
 
1180
    HostEntry *hostList, **hostPtr = &hostList;
 
1181
    AliasEntry *aliasList, **aliasPtr = &aliasList;
 
1182
    AclEntry *acList, **acPtr = &acList, *acl;
 
1183
    ListenEntry *listenList, **listenPtr = &listenList;
 
1184
    char *displayOrAlias, *hostOrAlias;
 
1185
    File file;
 
1186
    int nHosts, nAliases, nAcls, nListens, nChars, error, bad;
 
1187
    int i, len;
 
1188
 
 
1189
    nHosts = nAliases = nAcls = nListens = nChars = 0;
 
1190
    error = False;
 
1191
    if (!readFile(&file, fname, "XDMCP access control"))
 
1192
        goto sendacl;
 
1193
    while ((displayOrAlias = readWord(&file, &len, False))) {
 
1194
        if (*displayOrAlias == ALIAS_CHARACTER) {
 
1195
            if (!(*aliasPtr = Malloc(sizeof(AliasEntry)))) {
 
1196
                error = True;
 
1197
                break;
 
1198
            }
 
1199
            (*aliasPtr)->name = displayOrAlias + 1;
 
1200
            nChars += len;
 
1201
            (*aliasPtr)->hosts = nHosts;
 
1202
            (*aliasPtr)->pHosts = hostPtr;
 
1203
            (*aliasPtr)->nhosts = 0;
 
1204
            (*aliasPtr)->hasBad = False;
 
1205
            while ((hostOrAlias = readWord(&file, &len, True))) {
 
1206
                if (parseHost(&nHosts, &hostPtr, &nChars, hostOrAlias, len,
 
1207
                              PARSE_NO_BCAST))
 
1208
                    (*aliasPtr)->nhosts++;
 
1209
                else
 
1210
                    (*aliasPtr)->hasBad = True;
 
1211
            }
 
1212
            aliasPtr = &(*aliasPtr)->next;
 
1213
            nAliases++;
 
1214
        } else if (!strcmp(displayOrAlias, LISTEN_STRING)) {
 
1215
            if (!(*listenPtr = Malloc(sizeof(ListenEntry)))) {
 
1216
                error = True;
 
1217
                break;
 
1218
            }
 
1219
            (*listenPtr)->iface = nHosts;
 
1220
            if (!(hostOrAlias = readWord(&file, &len, True)) ||
 
1221
                !strcmp(hostOrAlias, WILDCARD_STRING) ||
 
1222
                !parseHost(&nHosts, &hostPtr, &nChars, hostOrAlias, len,
 
1223
                           PARSE_NO_BCAST | PARSE_NO_PAT | PARSE_NO_ALIAS))
 
1224
            {
 
1225
                (*listenPtr)->iface = -1;
 
1226
            }
 
1227
            (*listenPtr)->mcasts = nHosts;
 
1228
            (*listenPtr)->nmcasts = 0;
 
1229
            while ((hostOrAlias = readWord(&file, &len, True)))
 
1230
                if (parseHost(&nHosts, &hostPtr, &nChars, hostOrAlias, len,
 
1231
                              PARSE_NO_BCAST | PARSE_NO_PAT | PARSE_NO_ALIAS))
 
1232
                    (*listenPtr)->nmcasts++;
 
1233
            listenPtr = &(*listenPtr)->next;
 
1234
            nListens++;
 
1235
        } else {
 
1236
            if (!(*acPtr = Malloc(sizeof(AclEntry)))) {
 
1237
                error = True;
 
1238
                break;
 
1239
            }
 
1240
            (*acPtr)->flags = 0;
 
1241
            if (*displayOrAlias == NEGATE_CHARACTER) {
 
1242
                (*acPtr)->flags |= a_notAllowed;
 
1243
                displayOrAlias++;
 
1244
            } else if (*displayOrAlias == EQUAL_CHARACTER) {
 
1245
                displayOrAlias++;
 
1246
            }
 
1247
            (*acPtr)->entries = nHosts;
 
1248
            (*acPtr)->pEntries = hostPtr;
 
1249
            (*acPtr)->nentries = 1;
 
1250
            if (!parseHost(&nHosts, &hostPtr, &nChars, displayOrAlias, len,
 
1251
                           PARSE_NO_BCAST)) {
 
1252
                bad = True;
 
1253
                if ((*acPtr)->flags & a_notAllowed) {
 
1254
                    logError("XDMCP ACL: unresolved host in denying rule\n");
 
1255
                    error = True;
 
1256
                }
 
1257
            } else {
 
1258
                bad = False;
 
1259
            }
 
1260
            (*acPtr)->hosts = nHosts;
 
1261
            (*acPtr)->pHosts = hostPtr;
 
1262
            (*acPtr)->nhosts = 0;
 
1263
            while ((hostOrAlias = readWord(&file, &len, True))) {
 
1264
                if (!strcmp(hostOrAlias, CHOOSER_STRING)) {
 
1265
                    (*acPtr)->flags |= a_useChooser;
 
1266
                } else if (!strcmp(hostOrAlias, NOBROADCAST_STRING)) {
 
1267
                    (*acPtr)->flags |= a_notBroadcast;
 
1268
                } else {
 
1269
                    if (parseHost(&nHosts, &hostPtr, &nChars,
 
1270
                                  hostOrAlias, len, PARSE_NO_PAT))
 
1271
                        (*acPtr)->nhosts++;
 
1272
                }
 
1273
            }
 
1274
            if (!bad) {
 
1275
                acPtr = &(*acPtr)->next;
 
1276
                nAcls++;
 
1277
            }
 
1278
        }
 
1279
    }
 
1280
 
 
1281
    if (!nListens) {
 
1282
        if (!(*listenPtr = Malloc(sizeof(ListenEntry)))) {
 
1283
            error = True;
 
1284
        } else {
 
1285
            (*listenPtr)->iface = -1;
 
1286
            (*listenPtr)->mcasts = nHosts;
 
1287
            (*listenPtr)->nmcasts = 0;
 
1288
#if defined(IPv6) && defined(AF_INET6) && defined(XDM_DEFAULT_MCAST_ADDR6)
 
1289
            if (parseHost(&nHosts, &hostPtr, &nChars,
 
1290
                          XDM_DEFAULT_MCAST_ADDR6,
 
1291
                          sizeof(XDM_DEFAULT_MCAST_ADDR6) - 1,
 
1292
                          PARSE_ALL))
 
1293
                (*listenPtr)->nmcasts++;
 
1294
#endif
 
1295
            nListens++;
 
1296
        }
 
1297
    }
 
1298
 
 
1299
    for (acl = acList, i = 0; i < nAcls; i++, acl = acl->next)
 
1300
        if (checkHostlist(acl->pEntries, acl->nentries, aliasList, nAliases,
 
1301
                          0, (acl->flags & a_notAllowed) ? CHECK_NOT : 0) ||
 
1302
            checkHostlist(acl->pHosts, acl->nhosts, aliasList, nAliases,
 
1303
                          0, CHECK_NO_PAT))
 
1304
        {
 
1305
            error = True;
 
1306
        }
 
1307
 
 
1308
    if (error) {
 
1309
        nHosts = nAliases = nAcls = nListens = nChars = 0;
 
1310
      sendacl:
 
1311
        logError("No XDMCP requests will be granted\n");
 
1312
    }
 
1313
    gSendInt(nHosts);
 
1314
    gSendInt(nListens);
 
1315
    gSendInt(nAliases);
 
1316
    gSendInt(nAcls);
 
1317
    gSendInt(nChars);
 
1318
    for (i = 0; i < nHosts; i++, hostList = hostList->next) {
 
1319
        gSendInt(hostList->type);
 
1320
        switch (hostList->type) {
 
1321
        case HOST_ALIAS:
 
1322
            gSendStr(hostList->entry.aliasPattern);
 
1323
            break;
 
1324
        case HOST_PATTERN:
 
1325
            gSendStr(hostList->entry.hostPattern);
 
1326
            break;
 
1327
        case HOST_ADDRESS:
 
1328
            gSendArr(hostList->entry.displayAddress.hostAddrLen,
 
1329
                     hostList->entry.displayAddress.hostAddress);
 
1330
            gSendInt(hostList->entry.displayAddress.connectionType);
 
1331
            break;
 
1332
        }
 
1333
    }
 
1334
    for (i = 0; i < nListens; i++, listenList = listenList->next) {
 
1335
        gSendInt(listenList->iface);
 
1336
        gSendInt(listenList->mcasts);
 
1337
        gSendInt(listenList->nmcasts);
 
1338
    }
 
1339
    for (i = 0; i < nAliases; i++, aliasList = aliasList->next) {
 
1340
        gSendStr(aliasList->name);
 
1341
        gSendInt(aliasList->hosts);
 
1342
        gSendInt(aliasList->nhosts);
 
1343
    }
 
1344
    for (i = 0; i < nAcls; i++, acList = acList->next) {
 
1345
        gSendInt(acList->entries);
 
1346
        gSendInt(acList->nentries);
 
1347
        gSendInt(acList->hosts);
 
1348
        gSendInt(acList->nhosts);
 
1349
        gSendInt(acList->flags);
 
1350
    }
 
1351
}
 
1352
#endif
 
1353
 
 
1354
 
 
1355
int main(int argc ATTR_UNUSED, char **argv)
 
1356
{
 
1357
    DSpec dspec;
 
1358
    ValArr va;
 
1359
    char *ci, *disp, *dcls, *cfgfile;
 
1360
    int what;
 
1361
 
 
1362
    if (!(ci = getenv("CONINFO"))) {
 
1363
        fprintf(stderr, "This program is part of kdm and should not be run manually.\n");
 
1364
        return 1;
 
1365
    }
 
1366
    if (sscanf(ci, "%d %d", &rfd, &wfd) != 2)
 
1367
        return 1;
 
1368
 
 
1369
    InitLog();
 
1370
 
 
1371
    if ((debugLevel = gRecvInt()) & DEBUG_WCONFIG)
 
1372
        sleep(100);
 
1373
 
 
1374
/*    debug ("parsing command line\n");*/
 
1375
    if (**++argv)
 
1376
        kdmrc = *argv;
 
1377
/*
 
1378
    while (*++argv) {
 
1379
    }
 
1380
*/
 
1381
 
 
1382
    for (;;) {
 
1383
/*        debug ("Awaiting command ...\n");*/
 
1384
        if (!gRecvCmd(&what))
 
1385
            break;
 
1386
        switch (what) {
 
1387
        case GC_Files:
 
1388
/*            debug ("GC_Files\n");*/
 
1389
            readConfig();
 
1390
            copyValues(0, &secGeneral, 0, C_CONFIG);
 
1391
#ifdef XDMCP
 
1392
            copyValues(0, &secXdmcp, 0, C_CONFIG);
 
1393
            gSendInt(2);
 
1394
#else
 
1395
            gSendInt(1);
 
1396
#endif
 
1397
            gSendStr(kdmrc);
 
1398
            gSendInt(-1);
 
1399
#ifdef XDMCP
 
1400
            gSendNStr(VXaccess.str.ptr, VXaccess.str.len - 1);
 
1401
            gSendInt(0);
 
1402
#endif
 
1403
            for (; (what = gRecvInt()) != -1;)
 
1404
                switch (what) {
 
1405
                case GC_gGlobal:
 
1406
                case GC_gDisplay:
 
1407
                    gSendInt(0);
 
1408
                    break;
 
1409
#ifdef XDMCP
 
1410
                case GC_gXaccess:
 
1411
                    gSendInt(1);
 
1412
                    break;
 
1413
#endif
 
1414
                default:
 
1415
                    gSendInt(-1);
 
1416
                    break;
 
1417
                }
 
1418
            break;
 
1419
        case GC_GetConf:
 
1420
/*            debug("GC_GetConf\n");*/
 
1421
            memset(&va, 0, sizeof(va));
 
1422
            what = gRecvInt();
 
1423
            cfgfile = gRecvStr();
 
1424
            switch (what) {
 
1425
            case GC_gGlobal:
 
1426
/*                debug("GC_gGlobal\n");*/
 
1427
                debug("getting global config\n");
 
1428
                readConfig();
 
1429
                copyValues(&va, &secGeneral, 0, 0);
 
1430
#ifdef XDMCP
 
1431
                copyValues(&va, &secXdmcp, 0, 0);
 
1432
#endif
 
1433
                copyValues(&va, &secShutdown, 0, 0);
 
1434
                sendValues(&va);
 
1435
                break;
 
1436
            case GC_gDisplay:
 
1437
/*                debug("GC_gDisplay\n");*/
 
1438
                disp = gRecvStr();
 
1439
/*                debug(" Display %s\n", disp);*/
 
1440
                dcls = gRecvStr();
 
1441
/*                debug(" Class %s\n", dcls);*/
 
1442
                debug("getting config for display %s, class %s\n", disp, dcls);
 
1443
                mkDSpec(&dspec, disp, dcls ? dcls : "");
 
1444
                readConfig();
 
1445
                copyValues(&va, &sec_Core, &dspec, 0);
 
1446
                copyValues(&va, &sec_Greeter, &dspec, 0);
 
1447
                free(disp);
 
1448
                free(dcls);
 
1449
                sendValues(&va);
 
1450
                break;
 
1451
#ifdef XDMCP
 
1452
            case GC_gXaccess:
 
1453
                readAccessFile(cfgfile);
 
1454
                break;
 
1455
#endif
 
1456
            default:
 
1457
                debug("Unsupported config category %#x\n", what);
 
1458
            }
 
1459
            free(cfgfile);
 
1460
            break;
 
1461
        default:
 
1462
            debug("Unknown config command %#x\n", what);
 
1463
        }
 
1464
    }
 
1465
 
 
1466
/*    debug("Config reader exiting ...");*/
 
1467
    return EX_NORMAL;
 
1468
}