~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/Xprint/Init.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: Init.c,v 1.5 2001/03/07 17:31:33 pookie Exp $ */
 
2
/*
 
3
(c) Copyright 1996 Hewlett-Packard Company
 
4
(c) Copyright 1996 International Business Machines Corp.
 
5
(c) Copyright 1996 Sun Microsystems, Inc.
 
6
(c) Copyright 1996 Novell, Inc.
 
7
(c) Copyright 1996 Digital Equipment Corp.
 
8
(c) Copyright 1996 Fujitsu Limited
 
9
(c) Copyright 1996 Hitachi, Ltd.
 
10
 
 
11
Permission is hereby granted, free of charge, to any person obtaining a copy
 
12
of this software and associated documentation files (the "Software"), to deal
 
13
in the Software without restriction, including without limitation the rights
 
14
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
15
copies of the Software, and to permit persons to whom the Software is
 
16
furnished to do so, subject to the following conditions:
 
17
 
 
18
The above copyright notice and this permission notice shall be included in
 
19
all copies or substantial portions of the Software.
 
20
 
 
21
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
22
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
23
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
24
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 
25
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
26
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
27
 
 
28
Except as contained in this notice, the names of the copyright holders shall
 
29
not be used in advertising or otherwise to promote the sale, use or other
 
30
dealings in this Software without prior written authorization from said
 
31
copyright holders.
 
32
*/
 
33
/*******************************************************************
 
34
**
 
35
**    *********************************************************
 
36
**    *
 
37
**    *  File:          printer/Init.c
 
38
**    *
 
39
**    *  Contents:
 
40
**    *                 The InitOutput routine here would presumably
 
41
**    *                 be called from the normal server's InitOutput
 
42
**    *                 after all display screens have been added.
 
43
**    *                 There is are ifdef'd routines suitable for
 
44
**    *                 use in building a printer-only server.  Turn
 
45
**    *                 on the "PRINTER_ONLY_SERVER" define if this is
 
46
**    *                 to be the only ddx-level driver.
 
47
**    *
 
48
**    *  Copyright:     Copyright 1993,1995 Hewlett-Packard Company
 
49
**    *
 
50
**    *********************************************************
 
51
** 
 
52
********************************************************************/
 
53
/* $XFree86: xc/programs/Xserver/Xprint/Init.c,v 1.13 2001/12/21 21:02:04 dawes Exp $ */
 
54
 
 
55
#include <unistd.h>
 
56
#include <stdlib.h>
 
57
#include <stdio.h>
 
58
#include <ctype.h>
 
59
#include <signal.h>
 
60
#include <sys/types.h>
 
61
#include <sys/stat.h>
 
62
#include <string.h>
 
63
#include <locale.h>
 
64
#ifdef __hpux
 
65
#include <sys/sysmacros.h>
 
66
#endif
 
67
 
 
68
#include "X.h"
 
69
#define NEED_EVENTS 1
 
70
#include "Xproto.h"
 
71
#include <servermd.h>
 
72
 
 
73
#include "screenint.h"
 
74
#include "input.h"
 
75
#include "cursor.h"
 
76
#include "misc.h"
 
77
#include "windowstr.h"
 
78
#include "inputstr.h"
 
79
 
 
80
#include "gcstruct.h"
 
81
#include "fonts/fontstruct.h"
 
82
#include "errno.h"
 
83
 
 
84
typedef char *XPointer;
 
85
#define HAVE_XPointer 1
 
86
 
 
87
#define Status int
 
88
#include <Xresource.h>
 
89
 
 
90
#include "DiPrint.h"
 
91
#include "attributes.h"
 
92
 
 
93
#include "os.h"
 
94
 
 
95
static void GenericScreenInit(
 
96
    int index,
 
97
    ScreenPtr pScreen,
 
98
    int argc,
 
99
    char **argv);
 
100
static Bool InitPrintDrivers(
 
101
    int index,
 
102
    ScreenPtr pScreen,
 
103
    int argc,
 
104
    char **argv);
 
105
 
 
106
/*
 
107
 * The following two defines are used to build the name "X*printers", where
 
108
 * the "*" is replaced by the display number.  This is used to construct
 
109
 * the name of the default printers configuration file if the -XpFile
 
110
 * command line option was not specified.
 
111
 */
 
112
#define XNPRINTERSFILEPREFIX "/X"
 
113
#define XNPRINTERSFILESUFFIX "printers"
 
114
#define XPRINTERSFILENAME "Xprinters"
 
115
 
 
116
#define MODELDIRNAME "/models"
 
117
#define FONTDIRNAME "/fonts"
 
118
 
 
119
/*
 
120
 * The string LIST_QUEUES is fed to a shell to generate an ordered
 
121
 * list of available printers on the system. These string definitions
 
122
 * are taken from the file PrintSubSys.C within the code for the 
 
123
 * dtprintinfo program.
 
124
 */
 
125
#ifdef AIXV4
 
126
const char *LIST_QUEUES = "lsallq | grep -v '^bsh$' | sort";
 
127
#else
 
128
#ifdef hpux
 
129
const char *LIST_QUEUES = "LANG=C lpstat -v | "
 
130
                            "awk '"
 
131
                            " $2 == \"for\" "
 
132
                            "   { "
 
133
                            "      x = match($3, /:/); "
 
134
                            "      print substr($3, 1, x-1)"
 
135
                            "   }' | sort";
 
136
#else
 
137
#ifdef __osf__
 
138
  const char *LIST_QUEUES = "LANG=C lpstat -v | "
 
139
                            "nawk '"
 
140
                            " $2 == \"for\"    "
 
141
                            "   { print $4 }' "
 
142
                            "   | sort";
 
143
#else
 
144
#ifdef __uxp__
 
145
const char *LIST_QUEUES = "LANG=C lpstat -v | "
 
146
                            "nawk '"
 
147
                            " $4 == \"for\" "
 
148
                            "   { "
 
149
                            "      x = match($5, /:/); "
 
150
                            "      print substr($5, 1, x-1)"
 
151
                            "   }' | sort";
 
152
#else
 
153
#if defined(CSRG_BASED) || defined(linux) || defined(ISC) || defined(__GNUC__)
 
154
const char *LIST_QUEUES = "LANG=C lpc status | grep -v '^\t' | "
 
155
                            "sed -e /:/s/// | sort";
 
156
#else
 
157
const char *LIST_QUEUES = "LANG=C lpstat -v | "
 
158
                            "nawk '"
 
159
                            " $2 == \"for\" "
 
160
                            "   { "
 
161
                            "      x = match($3, /:/); "
 
162
                            "      print substr($3, 1, x-1)"
 
163
                            "   }' | sort";
 
164
#endif
 
165
#endif
 
166
#endif
 
167
#endif
 
168
#endif
 
169
 
 
170
#ifdef XPRASTERDDX
 
171
 
 
172
static
 
173
PixmapFormatRec RasterPixmapFormats[] = {
 
174
    { 1, 1, BITMAP_SCANLINE_PAD }
 
175
};
 
176
#define NUMRASTFORMATS  (sizeof RasterPixmapFormats)/(sizeof RasterPixmapFormats[0])
 
177
 
 
178
#include "raster/Raster.h"
 
179
 
 
180
#endif
 
181
 
 
182
#ifdef XPPCLDDX
 
183
 
 
184
static
 
185
PixmapFormatRec ColorPclPixmapFormats[] = {
 
186
    { 1, 1, BITMAP_SCANLINE_PAD },
 
187
    { 8, 8, BITMAP_SCANLINE_PAD },
 
188
    { 24,32, BITMAP_SCANLINE_PAD }
 
189
};
 
190
 
 
191
#define NUMCPCLFORMATS  (sizeof ColorPclPixmapFormats)/(sizeof ColorPclPixmapFormats[0])
 
192
 
 
193
#endif
 
194
 
 
195
#ifdef XPMONOPCLDDX
 
196
 
 
197
static
 
198
PixmapFormatRec MonoPclPixmapFormats[] = {
 
199
    { 1, 1, BITMAP_SCANLINE_PAD }
 
200
};
 
201
 
 
202
#define NUMMPCLFORMATS  (sizeof MonoPclPixmapFormats)/(sizeof MonoPclPixmapFormats[0])
 
203
 
 
204
#endif
 
205
 
 
206
#if defined(XPPCLDDX) || defined(XPMONOPCLDDX)
 
207
#include "pcl/Pcl.h"
 
208
#endif
 
209
 
 
210
#ifdef XPPSDDX
 
211
 
 
212
static
 
213
PixmapFormatRec PSPixmapFormats[] = {
 
214
    { 1, 1, BITMAP_SCANLINE_PAD },
 
215
    { 8, 8, BITMAP_SCANLINE_PAD },
 
216
    { 24,32, BITMAP_SCANLINE_PAD }
 
217
};
 
218
 
 
219
#define NUMPSFORMATS    (sizeof PSPixmapFormats)/(sizeof PSPixmapFormats[0])
 
220
 
 
221
#include "ps/Ps.h"
 
222
 
 
223
#endif
 
224
 
 
225
/*
 
226
 * The driverInitArray contains an entry for each driver the
 
227
 * server knows about. Each element contains pointers to pixmap formats, the
 
228
 * driver's initialization routine, and pointers to the driver's
 
229
 * attribute validation rec, and/or a driver function which 
 
230
 * returns the maximum medium width&height, and maximum resolution
 
231
 * given a printer name.  Either the validation rec OR the dimension
 
232
 * function can be NULL.  If the function is non-NULL then it
 
233
 * will be called, and will be passed the (possibly NULL) validation rec.
 
234
 * If the function is NULL, then XpGetMaxWidthHeightRes() is called.
 
235
 */
 
236
typedef struct _driverInitRec {
 
237
    char *driverName;
 
238
    pBFunc initFunc;
 
239
    XpValidatePoolsRec *pValRec;
 
240
    pVFunc dimensionsFunc;
 
241
    PixmapFormatRec *pFmts;
 
242
    int numFmts;
 
243
} driverInitRec;
 
244
 
 
245
static driverInitRec driverInits[] = {
 
246
#ifdef XPRASTERDDX
 
247
    {
 
248
        "XP-RASTER",
 
249
        InitializeRasterDriver,
 
250
        &RasterValidatePoolsRec,
 
251
        (pVFunc) NULL,
 
252
        RasterPixmapFormats,
 
253
        NUMRASTFORMATS
 
254
    },
 
255
#endif
 
256
#ifdef XPPCLDDX
 
257
    {
 
258
        "XP-PCL-COLOR",
 
259
        InitializeColorPclDriver,
 
260
        &PclValidatePoolsRec,
 
261
        (pVFunc) NULL,
 
262
        ColorPclPixmapFormats,
 
263
        NUMCPCLFORMATS
 
264
    },
 
265
#endif
 
266
#ifdef XPMONOPCLDDX
 
267
    {
 
268
        "XP-PCL-MONO",
 
269
        InitializeMonoPclDriver,
 
270
        &PclValidatePoolsRec,
 
271
        (pVFunc) NULL,
 
272
        MonoPclPixmapFormats,
 
273
        NUMMPCLFORMATS
 
274
    },
 
275
#endif
 
276
#ifdef XPPSDDX
 
277
    {
 
278
        "XP-POSTSCRIPT",
 
279
        InitializePsDriver,
 
280
        &PsValidatePoolsRec,
 
281
        (pVFunc) NULL,
 
282
        PSPixmapFormats,
 
283
        NUMPSFORMATS
 
284
    },
 
285
#endif
 
286
};
 
287
    
 
288
 
 
289
/*
 
290
 * The printerDb variable points to a list of PrinterDbEntry structs
 
291
 * which map printer names with screen numbers and driver names.
 
292
 */
 
293
typedef struct _printerDbEntry {
 
294
    struct _printerDbEntry *next;
 
295
    char *name;
 
296
    char *qualifier;
 
297
    int screenNum;
 
298
    char *driverName;
 
299
} PrinterDbEntry, *PrinterDbPtr;
 
300
 
 
301
static PrinterDbPtr printerDb = (PrinterDbPtr)NULL;
 
302
 
 
303
/*
 
304
 * The nameMap is a list used in initializing the attribute store
 
305
 * for each printer.  The list is freed once the printerDb is built
 
306
 * and the attribute stores for all printers have been initialized.
 
307
 */
 
308
typedef struct _nameMapEntry {
 
309
    struct _nameMapEntry *next;
 
310
    char *name;
 
311
    char *qualifier;
 
312
} NameMapEntry, *NameMapPtr;
 
313
 
 
314
static NameMapPtr nameMap = (NameMapPtr)NULL;
 
315
 
 
316
/*
 
317
 * The driverMap is a list which provides the mapping between driver names
 
318
 * and screen numbers. It is built and used 
 
319
 * by RehashPrinterList to correctly fill in the screenNum field in the
 
320
 * printerDb entries. The list is freed before RehashPrinterList terminates.
 
321
 */
 
322
typedef struct _driverMapping {
 
323
    struct _driverMapping *next;
 
324
    char *driverName;
 
325
    int screenNum;
 
326
} DriverMapEntry, *DriverMapPtr;
 
327
 
 
328
static const char configFilePath[] =
 
329
"/etc/dt/config/print:/usr/dt/config/print";
 
330
 
 
331
static const char printServerConfigDir[] = "XPSERVERCONFIGDIR";
 
332
 
 
333
static char *configFileName = (char *)NULL;
 
334
static Bool freeDefaultFontPath = FALSE;
 
335
static char *origFontPath = (char *)NULL;
 
336
 
 
337
/*
 
338
 * XprintOptions checks argv[i] to see if it is our command line
 
339
 * option specifying a configuration file name.  It returns the index
 
340
 * of the next option to process.
 
341
 */
 
342
int
 
343
XprintOptions(
 
344
    int argc,
 
345
    char **argv,
 
346
    int i)
 
347
{
 
348
    if(strcmp(argv[i], "-XpFile") == 0)
 
349
    {
 
350
        if ((i + 1) >= argc) {
 
351
            ddxUseMsg ();
 
352
            return i + 2;
 
353
        }
 
354
        configFileName = argv[i + 1];
 
355
        return i + 2;
 
356
    }
 
357
    else
 
358
        return i;
 
359
}
 
360
 
 
361
/************************************************************
 
362
 * GetInitFunc --
 
363
 *
 
364
 *      This routine is called from the InitPrintDrivers function.
 
365
 *      Given the name of a driver, return a pointer to the driver's
 
366
 *      initialization function.
 
367
 *
 
368
 * Results:
 
369
 *      Returns a pointer to the initialization function for the driver.
 
370
 * 
 
371
 *
 
372
 ************************************************************/
 
373
 
 
374
/*
 
375
typedef Bool (*pIFunc)();
 
376
static pIFunc
 
377
GetInitFunc(driverName)
 
378
*/
 
379
 
 
380
static pBFunc GetInitFunc(char *driverName)
 
381
{
 
382
    driverInitRec *pInitRec;
 
383
    int numDrivers = sizeof(driverInits)/sizeof(driverInitRec);
 
384
    int i;
 
385
 
 
386
    for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++)
 
387
    {
 
388
        if( !strcmp( driverName, pInitRec->driverName ) )
 
389
          return pInitRec->initFunc;
 
390
    }
 
391
 
 
392
    return 0;
 
393
}
 
394
 
 
395
static void
 
396
GetDimFuncAndRec(
 
397
    char *driverName, 
 
398
    XpValidatePoolsRec **pValRec,
 
399
    pVFunc *dimensionsFunc)
 
400
{
 
401
    driverInitRec *pInitRec;
 
402
    int numDrivers = sizeof(driverInits)/sizeof(driverInitRec);
 
403
    int i;
 
404
 
 
405
    for(pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++)
 
406
    {
 
407
        if( !strcmp( driverName, pInitRec->driverName ) )
 
408
        {
 
409
          *dimensionsFunc = pInitRec->dimensionsFunc;
 
410
          *pValRec = pInitRec->pValRec;
 
411
          return ;
 
412
        }
 
413
    }
 
414
 
 
415
    *dimensionsFunc = 0;
 
416
    *pValRec = 0;
 
417
    return;
 
418
}
 
419
 
 
420
static void
 
421
FreePrinterDb(void)
 
422
{
 
423
    PrinterDbPtr pCurEntry, pNextEntry;
 
424
 
 
425
    for(pCurEntry = printerDb, pNextEntry = 0;
 
426
        pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pNextEntry)
 
427
    {
 
428
        pNextEntry = pCurEntry->next;
 
429
        if(pCurEntry->name != (char *)NULL)
 
430
            xfree(pCurEntry->name);
 
431
        /*
 
432
         * We don't free the driver name, because it's expected to simply
 
433
         * be a pointer into the xrm database.
 
434
         */
 
435
        xfree(pCurEntry);
 
436
    }
 
437
    printerDb = 0;
 
438
}
 
439
 
 
440
/*
 
441
 * AddPrinterDbName allocates an entry in the printerDb list, and
 
442
 * initializes the "name".  It returns TRUE if the element was 
 
443
 * successfully added, and FALSE if an allocation error ocurred.
 
444
 * XXX AddPrinterDbName needs to check for (and not add) duplicate names.
 
445
 */
 
446
static Bool
 
447
AddPrinterDbName(char *name)
 
448
{
 
449
    PrinterDbPtr pEntry = (PrinterDbPtr)xalloc(sizeof(PrinterDbEntry));
 
450
 
 
451
    if(pEntry == (PrinterDbPtr)NULL) return FALSE;
 
452
    pEntry->name = strdup(name);
 
453
    pEntry->qualifier = (char *)NULL;
 
454
 
 
455
    if(printerDb == (PrinterDbPtr)NULL)
 
456
    {
 
457
        pEntry->next = (PrinterDbPtr)NULL;
 
458
        printerDb = pEntry;
 
459
    }
 
460
    else
 
461
    {
 
462
        pEntry->next = printerDb;
 
463
        printerDb = pEntry;
 
464
    }
 
465
    return TRUE;
 
466
}
 
467
 
 
468
static void
 
469
AugmentPrinterDb(const char *command)
 
470
{
 
471
    FILE *fp;
 
472
    char name[256];
 
473
 
 
474
    fp = popen(command, "r");
 
475
    /* XXX is a 256 character limit overly restrictive for printer names? */
 
476
    while(fgets(name, 256, fp) != (char *)NULL && strlen(name))
 
477
    {
 
478
        name[strlen(name) - 1] = (char)'\0'; /* strip the \n */
 
479
        AddPrinterDbName(name);
 
480
    }
 
481
    pclose(fp);
 
482
}
 
483
 
 
484
/*
 
485
 * FreeNameMap frees all remaining memory associated with the nameMap.
 
486
 */
 
487
static void
 
488
FreeNameMap(void)
 
489
{
 
490
    NameMapPtr pEntry, pTmp;
 
491
 
 
492
    for(pEntry = nameMap, pTmp = (NameMapPtr)NULL; 
 
493
        pEntry != (NameMapPtr)NULL;
 
494
        pEntry = pTmp)
 
495
    {
 
496
        if(pEntry->name != (char *)NULL)
 
497
            xfree(pEntry->name);
 
498
        if(pEntry->qualifier != (char *)NULL)
 
499
            xfree(pEntry->qualifier);
 
500
        pTmp = pEntry->next;
 
501
        xfree(pEntry);
 
502
    }
 
503
    nameMap = (NameMapPtr)NULL;
 
504
}
 
505
 
 
506
/*
 
507
 * AddNameMap adds an element to the nameMap linked list.
 
508
 */
 
509
static Bool
 
510
AddNameMap(char *name, char *qualifier)
 
511
{
 
512
    NameMapPtr pEntry;
 
513
 
 
514
    if((pEntry = (NameMapPtr)xalloc(sizeof(NameMapEntry))) == (NameMapPtr)NULL)
 
515
        return FALSE;
 
516
    pEntry->name = name;
 
517
    pEntry->qualifier = qualifier;
 
518
    pEntry->next = nameMap;
 
519
    nameMap = pEntry;
 
520
    return TRUE;
 
521
}
 
522
 
 
523
/*
 
524
 * MergeNameMap - puts the "map" names (aka qualifiers, aliases) into
 
525
 * the printerDb.  This should be called once, after both the printerDb
 
526
 * and nameMap lists are complete. When/if MergeNameMap finds a map for
 
527
 * an entry in the printerDb, the qualifier is _moved_ (not copied) to
 
528
 * the printerDb. This means that the qualifier pointer in the nameMap
 
529
 * is NULLed out.
 
530
 */
 
531
static void
 
532
MergeNameMap(void)
 
533
{
 
534
    NameMapPtr pMap;
 
535
    PrinterDbPtr pDb;
 
536
 
 
537
    for(pMap = nameMap; pMap != (NameMapPtr)NULL; pMap = pMap->next)
 
538
    {
 
539
        for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
 
540
        {
 
541
            if(!strcmp(pMap->name, pDb->name))
 
542
            {
 
543
                pDb->qualifier = pMap->qualifier;
 
544
                pMap->qualifier = (char *)NULL;
 
545
            }
 
546
        }
 
547
    }
 
548
}
 
549
 
 
550
/*
 
551
 * CreatePrinterAttrs causes the attribute stores to be built for
 
552
 * each printer in the printerDb.
 
553
 */
 
554
static void
 
555
CreatePrinterAttrs(void)
 
556
{
 
557
    PrinterDbPtr pDb;
 
558
 
 
559
    for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
 
560
    {
 
561
        XpBuildAttributeStore(pDb->name, (pDb->qualifier)? 
 
562
                              pDb->qualifier : pDb->name);
 
563
    }
 
564
}
 
565
 
 
566
#ifdef XPPSDDX
 
567
#define defaultDriver "XP-POSTSCRIPT"
 
568
#else
 
569
#ifdef XPPCLDDX
 
570
#define defaultDriver "XP-PCL-COLOR"
 
571
#else
 
572
#ifdef XPMONOPCLDDX
 
573
#define defaultDriver "XP-PCL-MONO"
 
574
#else
 
575
#define defaultDriver "XP-RASTER"
 
576
#endif
 
577
#endif
 
578
#endif
 
579
 
 
580
/*
 
581
 * StoreDriverNames -  queries the attribute store for the ddx-identifier.
 
582
 * if the ddx-identifier is not in the attribute database, then a default
 
583
 * ddx-identifier is store in both the attribute store for the printer,
 
584
 * and in the printerDb.
 
585
 * The ddx-identifier is stored in the printerDb for use in initializing
 
586
 * the screens.
 
587
 */
 
588
static void
 
589
StoreDriverNames(void)
 
590
{
 
591
    PrinterDbPtr pEntry;
 
592
 
 
593
    for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; 
 
594
        pEntry = pEntry->next)
 
595
    {
 
596
        pEntry->driverName = (char*)XpGetPrinterAttribute(pEntry->name, 
 
597
                                                          "xp-ddx-identifier");
 
598
        if(pEntry->driverName == (char *)NULL || 
 
599
           strlen(pEntry->driverName) == 0 ||
 
600
           GetInitFunc(pEntry->driverName) == 0)
 
601
        {
 
602
            if (pEntry->driverName && (strlen(pEntry->driverName) != 0)) {
 
603
                ErrorF("Xp Extension: Can't load driver %s\n", 
 
604
                       pEntry->driverName);
 
605
                ErrorF("              init function missing\n"); 
 
606
            }
 
607
 
 
608
            pEntry->driverName = defaultDriver;
 
609
            XpAddPrinterAttribute(pEntry->name,
 
610
                                  (pEntry->qualifier != (char *)NULL)?
 
611
                                  pEntry->qualifier : pEntry->name,
 
612
                                  "*xp-ddx-identifier", pEntry->driverName);
 
613
        }
 
614
    }
 
615
}
 
616
 
 
617
static char *
 
618
MbStrchr(
 
619
    char *str,
 
620
    int ch)
 
621
{
 
622
    size_t mbCurMax = MB_CUR_MAX;
 
623
    wchar_t targetChar, curChar;
 
624
    char tmpChar;
 
625
    int i, numBytes, byteLen;
 
626
 
 
627
    if(mbCurMax <= 1) return strchr(str, ch);
 
628
 
 
629
    tmpChar = (char)ch;
 
630
    mbtowc(&targetChar, &tmpChar, mbCurMax);
 
631
    for(i = 0, numBytes = 0, byteLen = strlen(str); i < byteLen; i += numBytes)
 
632
    {
 
633
        numBytes = mbtowc(&curChar, &str[i], mbCurMax);
 
634
        if(curChar == targetChar) return &str[i];
 
635
    }
 
636
    return (char *)NULL;
 
637
}
 
638
 
 
639
/*
 
640
 * GetConfigFileName - Looks for a "Xprinters" file in
 
641
 * $(XPRINTDIR)/$LANG/print, and then in $(XPRINTDIR)/C/print. If it
 
642
 * finds such a file, it returns the path to the file.  The returned
 
643
 * string must be freed by the caller.
 
644
 */
 
645
static char *
 
646
GetConfigFileName(void)
 
647
{
 
648
    /*
 
649
     * We need to find the system-wide file, if one exists.  This
 
650
     * file can be in either $(XPRINTDIR)/$LANG/print, or in
 
651
     * $(PRINTDIR)/C/print, and the file itself is named "Xprinters".
 
652
     */
 
653
    char *dirName, *filePath;
 
654
        
 
655
    /*
 
656
     * Check for a LANG-specific file.
 
657
     */
 
658
    if ((dirName = XpGetConfigDir(TRUE)) != 0)
 
659
    {
 
660
        filePath = (char *)xalloc(strlen(dirName) +
 
661
                                  strlen(XPRINTERSFILENAME) + 2);
 
662
 
 
663
        if(filePath == (char *)NULL)
 
664
        {
 
665
            xfree(dirName);
 
666
            return (char *)NULL;
 
667
        }
 
668
 
 
669
        sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME);
 
670
        xfree(dirName);
 
671
        if(access(filePath, R_OK) == 0)
 
672
            return filePath;
 
673
 
 
674
        xfree(filePath);
 
675
    }
 
676
 
 
677
    if ((dirName = XpGetConfigDir(FALSE)) != 0)
 
678
    {
 
679
        filePath = (char *)xalloc(strlen(dirName) +
 
680
                                  strlen(XPRINTERSFILENAME) + 2);
 
681
        if(filePath == (char *)NULL)
 
682
        {
 
683
            xfree(dirName);
 
684
            return (char *)NULL;
 
685
        }
 
686
        sprintf(filePath, "%s/%s", dirName, XPRINTERSFILENAME);
 
687
        xfree(dirName);
 
688
        if(access(filePath, R_OK) == 0)
 
689
            return filePath;
 
690
        xfree(filePath);
 
691
    }
 
692
    return (char *)NULL;
 
693
}
 
694
 
 
695
/*
 
696
 * BuildPrinterDb - reads the config file if it exists, and if necessary
 
697
 * executes a command such as lpstat to generate a list of printers.
 
698
 * XXX
 
699
 * XXX BuildPrinterDb must be rewritten to allow 16-bit characters in 
 
700
 * XXX printer names.  The will involve replacing the use of strtok() and its
 
701
 * XXX related functions.
 
702
 * XXX At the same time, BuildPrinterDb and it's support routines should have
 
703
 * XXX allocation error checking added.
 
704
 * XXX
 
705
 */
 
706
static PrinterDbPtr
 
707
BuildPrinterDb(void)
 
708
{
 
709
    Bool defaultAugment = TRUE, freeConfigFileName;
 
710
 
 
711
    if(configFileName && access(configFileName, R_OK) != 0)
 
712
    {
 
713
        ErrorF("Xp Extension: Can't open file %s\n", configFileName);
 
714
    }
 
715
    if(!configFileName && (configFileName = GetConfigFileName()))
 
716
        freeConfigFileName = TRUE;
 
717
    else
 
718
        freeConfigFileName = FALSE;
 
719
 
 
720
    if(configFileName != (char *)NULL && access(configFileName, R_OK) == 0)
 
721
    {
 
722
        char line[256];
 
723
        FILE *fp = fopen(configFileName, "r");
 
724
 
 
725
        while(fgets(line, 256, fp) != (char *)NULL)
 
726
        {
 
727
            char *tok, *ptr;
 
728
            if((tok = strtok(line, " \t\012")) != (char *)NULL)
 
729
            {
 
730
                if(tok[0] == (char)'#') continue;
 
731
                if(strcmp(tok, "Printer") == 0)
 
732
                {
 
733
                    while((tok = strtok((char *)NULL, " \t")) != (char *)NULL)
 
734
                    {
 
735
                        if ((ptr = MbStrchr(tok, '\012')) != 0)
 
736
                            *ptr = (char)'\0';
 
737
                        AddPrinterDbName(tok);
 
738
                    }
 
739
                }
 
740
                else if(strcmp(tok, "Map") == 0)
 
741
                {
 
742
                    char *name, *qualifier;
 
743
 
 
744
                    if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL)
 
745
                        continue;
 
746
                    name = strdup(tok);
 
747
                    if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL)
 
748
                    {
 
749
                        xfree(name);
 
750
                        continue;
 
751
                    }
 
752
                    qualifier = strdup(tok);
 
753
                    AddNameMap(name, qualifier);
 
754
                }
 
755
                else if(strcmp(tok, "Augment_Printer_List") == 0)
 
756
                {
 
757
                    if((tok = strtok((char *)NULL, " \t\012")) == (char *)NULL)
 
758
                        continue;
 
759
 
 
760
                    if(strcmp(tok, "%default%") == 0)
 
761
                        continue;
 
762
                    defaultAugment = FALSE;
 
763
                    if(strcmp(tok, "%none%") == 0)
 
764
                        continue;
 
765
                    AugmentPrinterDb(tok);
 
766
                }
 
767
                else
 
768
                    break; /* XXX Generate an error? */
 
769
            }
 
770
        }
 
771
        fclose(fp);
 
772
    }
 
773
 
 
774
    if(defaultAugment == TRUE)
 
775
    {
 
776
        AugmentPrinterDb(LIST_QUEUES);
 
777
    }
 
778
 
 
779
    MergeNameMap();
 
780
    FreeNameMap();
 
781
 
 
782
    /* Create the attribute stores for all printers */
 
783
    CreatePrinterAttrs();
 
784
 
 
785
    /*
 
786
     * Find the drivers for each printers, and store the driver names
 
787
     * in the printerDb
 
788
     */
 
789
    StoreDriverNames();
 
790
 
 
791
    if(freeConfigFileName)
 
792
    {
 
793
        xfree(configFileName);
 
794
        configFileName = (char *)NULL;
 
795
    }
 
796
 
 
797
    return printerDb;
 
798
}
 
799
 
 
800
static void
 
801
FreeDriverMap(DriverMapPtr driverMap)
 
802
{
 
803
    DriverMapPtr pCurEntry, pNextEntry;
 
804
 
 
805
    for(pCurEntry = driverMap, pNextEntry = (DriverMapPtr)NULL; 
 
806
        pCurEntry != (DriverMapPtr)NULL; pCurEntry = pNextEntry)
 
807
    {
 
808
        pNextEntry = pCurEntry->next;
 
809
        if(pCurEntry->driverName != (char *)NULL)
 
810
            xfree(pCurEntry->driverName);
 
811
        xfree(pCurEntry);
 
812
    }
 
813
}
 
814
 
 
815
/*
 
816
 * XpRehashPrinterList rebuilds the list of printers known to the
 
817
 * server.  It first walks the printerDb to build a table mapping
 
818
 * driver names and screen numbers, since this is not an easy mapping
 
819
 * to change in the sample server. The normal configuration files are
 
820
 * then read & parsed to create the new list of printers. Printers
 
821
 * which require drivers other than those already initialized are
 
822
 * deleted from the printerDb.  This leaves attribute stores in place
 
823
 * for inaccessible printers, but those stores will be cleaned up in
 
824
 * the next rehash or server recycle.
 
825
 */
 
826
int
 
827
XpRehashPrinterList(void)
 
828
{
 
829
    PrinterDbPtr pEntry, pPrev;
 
830
    DriverMapPtr driverMap = (DriverMapPtr)NULL, pDrvEnt;
 
831
    int result;
 
832
 
 
833
    /* Build driverMap */
 
834
    for(pEntry = printerDb; pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next)
 
835
    {
 
836
        for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL; 
 
837
            pDrvEnt = pDrvEnt->next)
 
838
        {
 
839
            if(!strcmp(pEntry->driverName, pDrvEnt->driverName))
 
840
                break;
 
841
        }
 
842
 
 
843
        if(pDrvEnt != (DriverMapPtr)NULL) 
 
844
            continue;
 
845
 
 
846
        if((pDrvEnt = (DriverMapPtr)xalloc(sizeof(DriverMapEntry))) == 
 
847
            (DriverMapPtr)NULL)
 
848
        {
 
849
            FreeDriverMap(driverMap);
 
850
            return BadAlloc;
 
851
        }
 
852
        pDrvEnt->driverName = strdup(pEntry->driverName);
 
853
        pDrvEnt->screenNum = pEntry->screenNum;
 
854
        pDrvEnt->next = driverMap;
 
855
        driverMap = pDrvEnt;
 
856
    }
 
857
 
 
858
    /* Free the old printerDb */
 
859
    FreePrinterDb();
 
860
 
 
861
    /* Free/Rehash attribute stores */
 
862
    if((result = XpRehashAttributes()) != Success)
 
863
        return result;
 
864
 
 
865
    /* Build a new printerDb */
 
866
    if(BuildPrinterDb() ==  (PrinterDbPtr)NULL)
 
867
        return BadAlloc;
 
868
 
 
869
    /* Walk PrinterDb & either store screenNum, or delete printerDb entry */
 
870
    for(pEntry = printerDb, pPrev = (PrinterDbPtr)NULL;
 
871
        pEntry != (PrinterDbPtr)NULL; pEntry = pEntry->next)
 
872
    {
 
873
        for(pDrvEnt = driverMap; pDrvEnt != (DriverMapPtr)NULL; 
 
874
            pDrvEnt = pDrvEnt->next)
 
875
        {
 
876
            if(!strcmp(printerDb->driverName, pDrvEnt->driverName))
 
877
                break;
 
878
        }
 
879
 
 
880
        /*
 
881
         * Either store the screen number, or delete the printerDb entry.
 
882
         * Deleting the entry leaves orphaned attribute stores, but they'll
 
883
         * get cleaned up at the next rehash or server recycle.
 
884
         */
 
885
        if(pDrvEnt != (DriverMapPtr)NULL) 
 
886
        {
 
887
            pEntry->screenNum = pDrvEnt->screenNum;
 
888
            pPrev = pEntry;
 
889
        }
 
890
        else {
 
891
            if(pPrev)
 
892
                pPrev->next = pEntry->next;
 
893
            else
 
894
                pPrev = pEntry->next;
 
895
            if(pEntry->name != (char *)NULL)
 
896
                xfree(pEntry->name);
 
897
            xfree(pEntry);
 
898
            pEntry = pPrev;
 
899
        }
 
900
    }
 
901
 
 
902
    FreeDriverMap(driverMap);
 
903
 
 
904
    return Success;
 
905
}
 
906
 
 
907
/*
 
908
 * ValidateFontDir looks for a valid font directory for the specified
 
909
 * printer model within the specified configuration directory. It returns
 
910
 * the directory name, or NULL if no valid font directory was found.
 
911
 * It is the caller's responsibility to free the returned font directory
 
912
 * name.
 
913
 */
 
914
static char *
 
915
ValidateFontDir(
 
916
    char *configDir, 
 
917
    char *modelName)
 
918
{
 
919
    char *pathName;
 
920
 
 
921
    if(!configDir || !modelName)
 
922
        return (char *)NULL;
 
923
 
 
924
    pathName = (char *)xalloc(strlen(configDir) + strlen(MODELDIRNAME) +
 
925
                              strlen(modelName) + strlen(FONTDIRNAME) + 
 
926
                              strlen("fonts.dir") + 5);
 
927
    if(!pathName)
 
928
        return (char *)NULL;
 
929
    sprintf(pathName, "%s/%s/%s/%s/%s", configDir, MODELDIRNAME, modelName,
 
930
            FONTDIRNAME, "fonts.dir");
 
931
    if(access(pathName, R_OK) != 0)
 
932
    {
 
933
        xfree(pathName);
 
934
        return (char *)NULL;
 
935
    }
 
936
    pathName[strlen(pathName) - 9] = (char)'\0'; /* erase fonts.dir */
 
937
    return pathName;
 
938
}
 
939
 
 
940
/*
 
941
 * FindFontDir returns a pointer to the path name of the font directory
 
942
 * for the specified printer model name, if such a directory exists.
 
943
 * The directory contents are superficially checked for validity.
 
944
 * The caller must free the returned char *.
 
945
 *
 
946
 * We first look in the locale-specific model-config directory, and
 
947
 * then fall back to the C language model-config directory.
 
948
 */
 
949
static char *
 
950
FindFontDir(
 
951
    char *modelName)
 
952
{
 
953
    char *configDir, *fontDir;
 
954
 
 
955
    if(!modelName || !strlen(modelName))
 
956
        return (char *)NULL;
 
957
    
 
958
    configDir = XpGetConfigDir(TRUE);
 
959
    if ((fontDir = ValidateFontDir(configDir, modelName)) != 0)
 
960
    {
 
961
        xfree(configDir);
 
962
        return fontDir;
 
963
    }
 
964
 
 
965
    if(configDir) 
 
966
        xfree(configDir);
 
967
    configDir = XpGetConfigDir(FALSE);
 
968
    fontDir = ValidateFontDir(configDir, modelName);
 
969
 
 
970
    xfree(configDir);
 
971
 
 
972
    return fontDir;
 
973
}
 
974
 
 
975
/*
 
976
 * AddToFontPath adds the specified font path element to the global
 
977
 * defaultFontPath string. It adds the keyword "PRINTER:" to the front
 
978
 * of the path to denote that this is a printer-specific font path
 
979
 * element.
 
980
 */
 
981
static char PATH_PREFIX[] = "PRINTER:";
 
982
static int PATH_PREFIX_LEN = sizeof(PATH_PREFIX) - 1; /* same as strlen() */
 
983
 
 
984
static void
 
985
AddToFontPath(
 
986
    char *pathName)
 
987
{
 
988
    char *newPath;
 
989
    Bool freeOldPath;
 
990
 
 
991
    if(defaultFontPath == origFontPath)
 
992
        freeOldPath = FALSE;
 
993
    else
 
994
        freeOldPath = TRUE;
 
995
 
 
996
    newPath = (char *)xalloc(strlen(defaultFontPath) + strlen(pathName) + 
 
997
                             PATH_PREFIX_LEN + 2);
 
998
 
 
999
    sprintf(newPath, "%s%s,%s", PATH_PREFIX, pathName, defaultFontPath);
 
1000
 
 
1001
    if(freeOldPath)
 
1002
        xfree(defaultFontPath);
 
1003
 
 
1004
    defaultFontPath = newPath;
 
1005
    return;
 
1006
}
 
1007
 
 
1008
/*
 
1009
 * AugmentFontPath adds printer-model-specific font path elements to
 
1010
 * the front of the font path global variable "defaultFontPath" (dix/globals.c).
 
1011
 * We can't call SetFontPath() because the font code has not yet been 
 
1012
 * initialized when InitOutput is called (from whence this routine is called).
 
1013
 *
 
1014
 * This utilizes the static variables origFontPath and 
 
1015
 * freeDefaultFontPath to track the original contents of defaultFontPath,
 
1016
 * and to properly free the modified version upon server recycle.
 
1017
 */
 
1018
static void
 
1019
AugmentFontPath(void)
 
1020
{
 
1021
    char *modelID, **allIDs = (char **)NULL;
 
1022
    PrinterDbPtr pDbEntry;
 
1023
    int numModels, i;
 
1024
 
 
1025
    if(!origFontPath)
 
1026
        origFontPath = defaultFontPath;
 
1027
 
 
1028
    if(freeDefaultFontPath)
 
1029
    {
 
1030
        xfree(defaultFontPath);
 
1031
        defaultFontPath = origFontPath;
 
1032
        freeDefaultFontPath = FALSE;
 
1033
    }
 
1034
 
 
1035
    /*
 
1036
     * Build a list of printer models to check for internal fonts.
 
1037
     */
 
1038
    for(pDbEntry = printerDb, numModels = 0; 
 
1039
        pDbEntry != (PrinterDbPtr)NULL; 
 
1040
        pDbEntry = pDbEntry->next)
 
1041
    {
 
1042
        modelID =
 
1043
            (char*)XpGetPrinterAttribute(pDbEntry->name,
 
1044
                                         "xp-model-identifier");
 
1045
 
 
1046
        if(modelID && strlen(modelID) != 0)
 
1047
        {
 
1048
            /* look for current model in the list of allIDs */
 
1049
            for(i = 0; i < numModels; i++)
 
1050
            {
 
1051
                if(!strcmp(modelID, allIDs[i]))
 
1052
                {
 
1053
                    modelID = (char *)NULL;
 
1054
                    break;
 
1055
                }
 
1056
            }
 
1057
        }
 
1058
 
 
1059
        /*
 
1060
         * If this printer's model-identifier isn't in the allIDs list,
 
1061
         * then add it to allIDs.
 
1062
         */
 
1063
        if(modelID && strlen(modelID) != 0)
 
1064
        {
 
1065
            allIDs = (char **)xrealloc(allIDs, (numModels+2) * sizeof(char *));
 
1066
            if(allIDs == (char **)NULL)
 
1067
                return;
 
1068
            allIDs[numModels] = modelID;
 
1069
            allIDs[numModels + 1] = (char *)NULL;
 
1070
            numModels++;
 
1071
        }
 
1072
    }
 
1073
 
 
1074
    /* for each model, check for a valid font directory, and add it to
 
1075
     * the front of defaultFontPath.
 
1076
     */
 
1077
    for(i = 0; allIDs != (char **)NULL && allIDs[i] != (char *)NULL; i ++)
 
1078
    {
 
1079
        char *fontDir;
 
1080
        if ((fontDir = FindFontDir(allIDs[i])) != 0)
 
1081
        {
 
1082
            AddToFontPath(fontDir);
 
1083
            xfree(fontDir);
 
1084
            freeDefaultFontPath = TRUE;
 
1085
        }
 
1086
    }
 
1087
 
 
1088
    if(allIDs)
 
1089
        xfree(allIDs);
 
1090
 
 
1091
    return;
 
1092
}
 
1093
 
 
1094
/*
 
1095
 * XpClientIsBitmapClient is called by the font code to find out if
 
1096
 * a particular client should be granted access to bitmap fonts.
 
1097
 * This function works by
 
1098
 * calling XpContextOfClient (in Xserver/Xext/xprint.c) to determine
 
1099
 * the context associated with the client, and then queries the context's
 
1100
 * attributes to determine whether the bitmap fonts should be visible.
 
1101
 * It looks at the value of the xp-listfonts-mode document/page attribute to 
 
1102
 * see if xp-list-glyph-fonts has been left out of the mode list. Only
 
1103
 * if the xp-listfonts-mode attribute exists, and it does not contain
 
1104
 * xp-list-glyph-fonts does this function return FALSE. In any other
 
1105
 * case the funtion returns TRUE, indicating that the bitmap fonts 
 
1106
 * should be visible to the client.
 
1107
 */
 
1108
Bool
 
1109
XpClientIsBitmapClient(
 
1110
    ClientPtr client)
 
1111
{
 
1112
    XpContextPtr pContext;
 
1113
    char *mode;
 
1114
 
 
1115
    if(!(pContext = XpContextOfClient(client)))
 
1116
        return TRUE;
 
1117
 
 
1118
    /*
 
1119
     * Check the page attributes, and if it's not defined there, then
 
1120
     * check the document attributes.
 
1121
     */
 
1122
    mode = XpGetOneAttribute(pContext, XPPageAttr, "xp-listfonts-mode");
 
1123
    if(!mode || !strlen(mode))
 
1124
    {
 
1125
        mode = XpGetOneAttribute(pContext, XPDocAttr, "xp-listfonts-mode");
 
1126
        if(!mode || !strlen(mode))
 
1127
            return TRUE;
 
1128
    }
 
1129
    
 
1130
    if(!strstr(mode, "xp-list-glyph-fonts"))
 
1131
        return FALSE;
 
1132
 
 
1133
    return TRUE;
 
1134
}
 
1135
/*
 
1136
 * XpClientIsPrintClient is called by the font code to find out if
 
1137
 * a particular client has set a context which references a printer
 
1138
 * which utilizes a particular font path.  This function works by
 
1139
 * calling XpContextOfClient (in Xserver/Xext/xprint.c) to determine
 
1140
 * the context associated with the client, and then looks up the
 
1141
 * font directory for the context.  The font directory is then compared
 
1142
 * with the directory specified in the FontPathElement which is passed in.
 
1143
 */
 
1144
Bool
 
1145
XpClientIsPrintClient(
 
1146
    ClientPtr client,
 
1147
    FontPathElementPtr fpe)
 
1148
{
 
1149
    XpContextPtr pContext;
 
1150
    char *modelID, *fontDir;
 
1151
 
 
1152
    if(!(pContext = XpContextOfClient(client)))
 
1153
        return FALSE;
 
1154
 
 
1155
    if (!fpe)
 
1156
        return TRUE;
 
1157
 
 
1158
    modelID = XpGetOneAttribute(pContext, XPPrinterAttr, "xp-model-identifier");
 
1159
    if(!modelID || !strlen(modelID))
 
1160
        return FALSE;
 
1161
    
 
1162
    if(!(fontDir = FindFontDir(modelID)))
 
1163
        return FALSE;
 
1164
 
 
1165
    /*
 
1166
     * The grunge here is to ignore the PATH_PREFIX at the front of the
 
1167
     * fpe->name.
 
1168
     */
 
1169
    if(fpe->name_length < PATH_PREFIX_LEN || 
 
1170
       (strlen(fontDir) != (unsigned)(fpe->name_length - PATH_PREFIX_LEN)) ||
 
1171
       strncmp(fontDir, fpe->name + PATH_PREFIX_LEN, 
 
1172
               fpe->name_length - PATH_PREFIX_LEN))
 
1173
    {
 
1174
        xfree(fontDir);
 
1175
        return FALSE;
 
1176
    }
 
1177
    xfree(fontDir);
 
1178
    return TRUE;
 
1179
}
 
1180
 
 
1181
static void
 
1182
AddFormats(ScreenInfo *pScreenInfo, char *driverName)
 
1183
{
 
1184
    int i, j;
 
1185
    driverInitRec *pInitRec;
 
1186
    int numDrivers = sizeof(driverInits)/sizeof(driverInitRec);
 
1187
    PixmapFormatRec *formats;
 
1188
    int numfmts;
 
1189
 
 
1190
    for (pInitRec = driverInits, i = 0; i < numDrivers; pInitRec++, i++)
 
1191
    {
 
1192
        if ( !strcmp( driverName, pInitRec->driverName ) )
 
1193
            break;
 
1194
    }
 
1195
    if (i >= numDrivers)
 
1196
        return;
 
1197
    formats = pInitRec->pFmts;
 
1198
    numfmts = pInitRec->numFmts;
 
1199
    for (i = 0; i < numfmts && pScreenInfo->numPixmapFormats < MAXFORMATS; i++)
 
1200
    {
 
1201
        for (j = 0; j < pScreenInfo->numPixmapFormats; j++) {
 
1202
            if (pScreenInfo->formats[j].depth == formats[i].depth &&
 
1203
                pScreenInfo->formats[j].bitsPerPixel == formats[i].bitsPerPixel &&
 
1204
                pScreenInfo->formats[j].scanlinePad == formats[i].scanlinePad)
 
1205
                break;
 
1206
        }
 
1207
        if (j == pScreenInfo->numPixmapFormats) {
 
1208
            pScreenInfo->formats[j] = formats[i];
 
1209
            pScreenInfo->numPixmapFormats++;
 
1210
        }
 
1211
    }
 
1212
}
 
1213
 
 
1214
/************************************************************
 
1215
 * PrinterInitOutput --
 
1216
 *      This routine is to be called from a ddx's InitOutput
 
1217
 *      during the server startup initialization, and when
 
1218
 *      the server is to be reset.  The routine creates the
 
1219
 *      screens associated with configured printers by calling
 
1220
 *      dix:AddScreen.  The configuration information comes from a
 
1221
 *      database read from the X*printers file.
 
1222
 *
 
1223
 * Results:
 
1224
 *      The array of ScreenRec pointers referenced by
 
1225
 *      pScreenInfo->screen is increased by the addition
 
1226
 *      of the printer screen(s), as is the value of
 
1227
 *      pScreenInfo->numScreens.  This is done via calls
 
1228
 *      to AddScreen() in dix.
 
1229
 *
 
1230
 ************************************************************/
 
1231
 
 
1232
void
 
1233
PrinterInitOutput(
 
1234
     ScreenInfo *pScreenInfo,
 
1235
     int argc,
 
1236
     char **argv)
 
1237
{
 
1238
    PrinterDbPtr pDb, pDbEntry;
 
1239
    int driverCount = 0, i;
 
1240
    char **driverNames;
 
1241
    char *configDir;
 
1242
 
 
1243
    /* 
 
1244
     * this little test is just a warning at startup to make sure
 
1245
     * that the config directory exists.
 
1246
     *
 
1247
     * what this ugly looking if says is that if both ways of
 
1248
     * calling configDir works and both directories don't exist, 
 
1249
     * then print an error saying we can't find the non-lang one.
 
1250
     */
 
1251
    if (((configDir = XpGetConfigDir(TRUE)) != NULL) && 
 
1252
        (access(configDir, F_OK) == 0))
 
1253
    {
 
1254
        xfree(configDir);
 
1255
    }
 
1256
    else if (((configDir = XpGetConfigDir(FALSE)) != NULL) &&
 
1257
             (access(configDir, F_OK) == 0))
 
1258
    {
 
1259
        xfree(configDir);
 
1260
    }
 
1261
    else {
 
1262
        ErrorF("Xp Extension: could not find config dir %s\n",
 
1263
               configDir ? configDir : XPRINTDIR);
 
1264
 
 
1265
        if (configDir) xfree(configDir);
 
1266
    }
 
1267
 
 
1268
    if(printerDb != (PrinterDbPtr)NULL)
 
1269
        FreePrinterDb();
 
1270
        
 
1271
    /*
 
1272
     * Calling BuildPrinterDb serves to build the printer database,
 
1273
     * and to initialize the attribute store for each printer.
 
1274
     * The driver can, if it so desires, modify the attribute
 
1275
     * store at a later time.
 
1276
     */
 
1277
    if((pDb = BuildPrinterDb()) ==  (PrinterDbPtr)NULL) return;
 
1278
 
 
1279
    /*
 
1280
     * We now have to decide how many screens to initialize, and call
 
1281
     * AddScreen for each one. The printerDb must be properly initialized
 
1282
     * for at least one screen's worth of printers prior to calling AddScreen
 
1283
     * because InitPrintDrivers reads the printerDb to determine which 
 
1284
     * driver(s) to init on a particular screen.
 
1285
     * We put each driver's printers on a different
 
1286
     * screen, and call AddScreen for each screen/driver pair.
 
1287
     */
 
1288
    /* count the number of printers */
 
1289
    for(pDbEntry = pDb, driverCount = 0; pDbEntry != (PrinterDbPtr)NULL; 
 
1290
        pDbEntry = pDbEntry->next, driverCount++)
 
1291
            ;
 
1292
    /*
 
1293
     * Allocate memory for the worst case - a driver per printer
 
1294
     */
 
1295
    driverNames = (char **)xalloc(sizeof(char *) * driverCount);
 
1296
 
 
1297
    /*
 
1298
     * Assign the driver for the first printer to the first screen
 
1299
     */
 
1300
    pDb->screenNum = screenInfo.numScreens;
 
1301
    driverNames[0] = pDb->driverName;
 
1302
    driverCount = 1;
 
1303
    AddFormats(pScreenInfo, pDb->driverName);
 
1304
 
 
1305
    /*
 
1306
     * For each printer, look to see if its driver is already assigned
 
1307
     * to a screen, and if so copy that screen number into the printerDb.
 
1308
     * Otherwise, assign a new screen number to the driver for this
 
1309
     * printer.
 
1310
     */
 
1311
    for(pDbEntry = pDb; pDbEntry != (PrinterDbPtr)NULL; 
 
1312
        pDbEntry = pDbEntry->next)
 
1313
    {
 
1314
        Bool foundMatch;
 
1315
 
 
1316
        for(i = 0, foundMatch = FALSE; i < driverCount; i++)
 
1317
        {
 
1318
            if(!strcmp(driverNames[i], pDbEntry->driverName))
 
1319
            {
 
1320
                foundMatch = TRUE;
 
1321
                pDbEntry->screenNum = screenInfo.numScreens + i;
 
1322
                break;
 
1323
            }
 
1324
        }
 
1325
        if(foundMatch == FALSE)
 
1326
        {
 
1327
            driverNames[driverCount] = pDbEntry->driverName;
 
1328
            pDbEntry->screenNum = screenInfo.numScreens + driverCount;
 
1329
            AddFormats(pScreenInfo, pDbEntry->driverName);
 
1330
            driverCount++;
 
1331
        }
 
1332
    }
 
1333
       
 
1334
    for(i = 0; i < driverCount; i++)
 
1335
    {
 
1336
        int curScreen = screenInfo.numScreens;
 
1337
        if(AddScreen(InitPrintDrivers, argc, argv) < 0)
 
1338
        {
 
1339
            PrinterDbPtr pPrev;
 
1340
            /* 
 
1341
             * AddScreen failed, so we pull the associated printers 
 
1342
             * from the list.
 
1343
             */
 
1344
            ErrorF("Xp Extension: Could not add screen for driver %s\n",
 
1345
                   driverNames[i]);
 
1346
            for(pPrev = pDbEntry = printerDb; pDbEntry != (PrinterDbPtr)NULL; 
 
1347
                pDbEntry = pDbEntry->next)
 
1348
            {
 
1349
                if(pDbEntry->screenNum == curScreen)
 
1350
                {
 
1351
                    if(pPrev == printerDb)
 
1352
                    {
 
1353
                        printerDb = pDbEntry->next;
 
1354
                        pPrev = printerDb;
 
1355
                    }
 
1356
                    else
 
1357
                        pPrev->next = pDbEntry->next;
 
1358
 
 
1359
                    xfree(pDbEntry->name);
 
1360
                    xfree(pDbEntry);
 
1361
                    pDbEntry = pPrev;
 
1362
                }
 
1363
                else 
 
1364
                {
 
1365
                    if(pDbEntry->screenNum > curScreen)
 
1366
                        pDbEntry->screenNum--;
 
1367
                    pPrev = pDbEntry;
 
1368
                }
 
1369
            }
 
1370
        }
 
1371
    }
 
1372
 
 
1373
    xfree(driverNames);
 
1374
 
 
1375
    AugmentFontPath();
 
1376
 
 
1377
    if(pScreenInfo->numScreens > MAXSCREENS)
 
1378
    {
 
1379
        ErrorF("The number of printer screens requested ");
 
1380
        ErrorF("exceeds the allowable limit of %d screens.\n", MAXSCREENS);
 
1381
        ErrorF("Please reduce the number of requested printers in your ");
 
1382
        ErrorF("\nX%sprinters file.", display);
 
1383
        ErrorF("Server exiting...\n");
 
1384
        exit(-1);
 
1385
    }
 
1386
}
 
1387
 
 
1388
/*
 
1389
 * InitPrintDrivers is called from dix:AddScreen.  It in turn calls the
 
1390
 * driver initialization routine for any and all drivers which are
 
1391
 * implicated in supporting printers on the particular screen number
 
1392
 * specified by the "index" parameter.  The printerDb variable is used
 
1393
 * to determine which printers are to be associated with a particular
 
1394
 * screen.
 
1395
 */
 
1396
static Bool
 
1397
InitPrintDrivers(
 
1398
    int index,
 
1399
    ScreenPtr pScreen,
 
1400
    int argc,
 
1401
    char **argv)
 
1402
{
 
1403
    PrinterDbPtr pDb, pDb2;
 
1404
 
 
1405
    GenericScreenInit(index, pScreen, argc, argv);
 
1406
 
 
1407
    for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
 
1408
    {
 
1409
        if(pDb->screenNum == index)
 
1410
        {
 
1411
            Bool callInit = TRUE;
 
1412
            for(pDb2 = printerDb; pDb2 != pDb; pDb2 = pDb2->next)
 
1413
            {
 
1414
                if(!strcmp(pDb->driverName, pDb2->driverName))
 
1415
                {
 
1416
                    callInit = FALSE;
 
1417
                    break;
 
1418
                }
 
1419
            }
 
1420
            if(callInit == TRUE)
 
1421
            {
 
1422
                pBFunc initFunc;
 
1423
                initFunc = GetInitFunc(pDb->driverName);
 
1424
                if(initFunc(index, pScreen, argc, argv) == FALSE)
 
1425
                {
 
1426
                    /* XXX - What do I do if the driver's init fails? */
 
1427
                }
 
1428
            }
 
1429
        }
 
1430
    }
 
1431
    return TRUE;
 
1432
}
 
1433
 
 
1434
void
 
1435
_XpVoidNoop(void)
 
1436
{
 
1437
    return;
 
1438
}
 
1439
 
 
1440
Bool
 
1441
_XpBoolNoop(void)
 
1442
{
 
1443
    return TRUE;
 
1444
}
 
1445
 
 
1446
/*
 
1447
 * GenericScreenInit - The common initializations required by all
 
1448
 * printer screens and drivers.  It sets the screen's cursor functions
 
1449
 * to Noops, and computes the maximum screen (i.e. medium) dimensions.
 
1450
 */
 
1451
 
 
1452
static void
 
1453
GenericScreenInit(
 
1454
     int index,
 
1455
     ScreenPtr pScreen,
 
1456
     int argc,
 
1457
     char **argv)
 
1458
{
 
1459
    float fWidth, fHeight, maxWidth, maxHeight;
 
1460
    unsigned short width, height;
 
1461
    PrinterDbPtr pDb;
 
1462
    int res, maxRes;
 
1463
    
 
1464
    /*
 
1465
     * Set the cursor ops to no-op functions.
 
1466
     */
 
1467
    pScreen->DisplayCursor = (DisplayCursorProcPtr)_XpBoolNoop;
 
1468
    pScreen->RealizeCursor = (RealizeCursorProcPtr)_XpBoolNoop;
 
1469
    pScreen->UnrealizeCursor = (UnrealizeCursorProcPtr)_XpBoolNoop;
 
1470
    pScreen->SetCursorPosition = (SetCursorPositionProcPtr)_XpBoolNoop;
 
1471
    pScreen->ConstrainCursor = (ConstrainCursorProcPtr)_XpVoidNoop;
 
1472
    pScreen->CursorLimits = (CursorLimitsProcPtr)_XpVoidNoop;
 
1473
    pScreen->RecolorCursor = (RecolorCursorProcPtr)_XpVoidNoop;
 
1474
 
 
1475
    /*
 
1476
     * Find the largest paper size for all the printers on the given
 
1477
     * screen.
 
1478
     */
 
1479
    maxRes = 0;
 
1480
    maxWidth = maxHeight = 0.0;
 
1481
    for( pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
 
1482
      {
 
1483
        if(pDb->screenNum == index)
 
1484
        {
 
1485
            XpValidatePoolsRec *pValRec;
 
1486
            pVFunc dimensionsFunc;
 
1487
 
 
1488
            GetDimFuncAndRec(pDb->driverName, &pValRec, &dimensionsFunc);
 
1489
            if(dimensionsFunc != (pVFunc)NULL)
 
1490
                dimensionsFunc(pDb->name, pValRec, &fWidth, &fHeight, &res);
 
1491
            else
 
1492
                XpGetMaxWidthHeightRes(pDb->name, pValRec, &fWidth, 
 
1493
                                       &fHeight, &res);
 
1494
            if( res > maxRes )
 
1495
              maxRes = res;
 
1496
            if( fWidth > maxWidth )
 
1497
              maxWidth = fWidth;
 
1498
            if( fHeight > maxHeight )
 
1499
              maxHeight = fHeight;
 
1500
          }
 
1501
      }
 
1502
    
 
1503
    width = (unsigned short) (maxWidth * maxRes / 25.4);
 
1504
    height = (unsigned short) (maxHeight * maxRes / 25.4);
 
1505
    pScreen->width = pScreen->height = ( width > height ) ? width :
 
1506
      height;
 
1507
    
 
1508
    pScreen->mmWidth = pScreen->mmHeight = ( maxWidth > maxHeight ) ?
 
1509
                                           (unsigned short)(maxWidth + 0.5) : 
 
1510
                                           (unsigned short)(maxHeight + 0.5);
 
1511
}
 
1512
 
 
1513
/*
 
1514
 * QualifyName - takes an unqualified file name such as X6printers and
 
1515
 * a colon-separated list of directory path names such as 
 
1516
 * /etc/opt/dt:/opt/dt/config.
 
1517
 * 
 
1518
 * Returns a fully qualified file path name such as /etc/opt/dt/X6printers.
 
1519
 * The returned value is malloc'd, and the caller is responsible for 
 
1520
 * freeing the associated memory.
 
1521
 */
 
1522
static char *
 
1523
QualifyName(
 
1524
    char *fileName,
 
1525
    char *searchPath)
 
1526
{
 
1527
    char * curPath = searchPath;
 
1528
    char * nextPath;
 
1529
    char * chance;
 
1530
    FILE *pFile;
 
1531
 
 
1532
    if (fileName == NULL || searchPath == NULL)
 
1533
      return NULL;
 
1534
 
 
1535
    while (1) {
 
1536
      if ((nextPath = strchr(curPath, ':')) != NULL)
 
1537
        *nextPath = 0;
 
1538
  
 
1539
      chance = (char *)xalloc(strlen(curPath) + strlen(fileName) + 2);
 
1540
      sprintf(chance,"%s/%s",curPath,fileName);
 
1541
  
 
1542
      /* see if we can read from the file */
 
1543
      if((pFile = fopen(chance, "r")) != (FILE *)NULL)
 
1544
      {
 
1545
        fclose(pFile);
 
1546
        /* ... restore the colon, .... */
 
1547
        if (nextPath)
 
1548
          *nextPath = ':';
 
1549
  
 
1550
        return chance;
 
1551
      }
 
1552
  
 
1553
      xfree(chance);
 
1554
 
 
1555
      if (nextPath == NULL) /* End of path list? */
 
1556
        break;
 
1557
  
 
1558
      /* try the next path */
 
1559
      curPath = nextPath + 1;
 
1560
    }
 
1561
    return NULL;
 
1562
}
 
1563
 
 
1564
/*
 
1565
 * FillPrinterListEntry fills in a single XpDiListEntry element with data
 
1566
 * derived from the supplied PrinterDbPtr element.
 
1567
 *
 
1568
 * XXX A smarter (i.e. future) version of this routine might inspect the
 
1569
 * XXX "locale" parameter and attempt to match the "description" and
 
1570
 * XXX "localeName" elements of the XpDiListEntry to the specified locale.
 
1571
 */
 
1572
static void
 
1573
FillPrinterListEntry(
 
1574
    XpDiListEntry *pEntry,
 
1575
    PrinterDbPtr pDb,
 
1576
    int localeLen,
 
1577
    char *locale)
 
1578
{
 
1579
    static char *localeStr = (char *)NULL;
 
1580
 
 
1581
    if(localeStr == (char *)NULL)
 
1582
        localeStr = strdup(setlocale(LC_ALL, (const char *)NULL));
 
1583
 
 
1584
    pEntry->name = pDb->name;
 
1585
    pEntry->description =
 
1586
        (char*)XpGetPrinterAttribute(pDb->name, "descriptor");
 
1587
    pEntry->localeName = localeStr;
 
1588
    pEntry->rootWinId = WindowTable[pDb->screenNum]->drawable.id;
 
1589
}
 
1590
 
 
1591
/*
 
1592
 * GetPrinterListInfo fills in the XpDiListEntry struct pointed to by the
 
1593
 * parameter pEntry with the information regarding the printer specified
 
1594
 * by the name and nameLen parameters.  The pointers placed in the 
 
1595
 * XpDiListEntry structure MUST NOT be freed by the caller.  They are
 
1596
 * pointers into existing long-lived databases.
 
1597
 *
 
1598
 */
 
1599
static Bool
 
1600
GetPrinterListInfo(
 
1601
    XpDiListEntry *pEntry,
 
1602
    int nameLen,
 
1603
    char *name,
 
1604
    int localeLen,
 
1605
    char *locale)
 
1606
{
 
1607
    PrinterDbPtr pDb;
 
1608
 
 
1609
    for(pDb = printerDb; pDb != (PrinterDbPtr)NULL; pDb = pDb->next)
 
1610
    {
 
1611
        if (strlen(pDb->name) == (unsigned)nameLen
 
1612
        && !strncmp(pDb->name, name, nameLen))
 
1613
        {
 
1614
            FillPrinterListEntry(pEntry, pDb, localeLen, locale);
 
1615
            return TRUE;
 
1616
        }
 
1617
    }
 
1618
    return FALSE;
 
1619
}
 
1620
 
 
1621
/*
 
1622
 * XpDiFreePrinterList is the approved method of releasing memory used
 
1623
 * for a printer list.
 
1624
 */
 
1625
void
 
1626
XpDiFreePrinterList(XpDiListEntry **list)
 
1627
{
 
1628
    int i;
 
1629
 
 
1630
    for(i = 0; list[i] != (XpDiListEntry *)NULL; i++)
 
1631
        xfree(list[i]);
 
1632
    xfree(list);
 
1633
}
 
1634
 
 
1635
/*
 
1636
 * XpDiGetPrinterList returns a pointer to a NULL-terminated array of
 
1637
 * XpDiListEntry pointers.  Each entry structure contains the name, 
 
1638
 * description, root window, and locale of a printer.  The call returns
 
1639
 * either a list of all printers configured on the server, or it returns
 
1640
 * the information for one specific printer depending on the values passed
 
1641
 * in.  Non-NULL values passed in indicate that only the information for
 
1642
 * the one specific printer is desired, while NULL values indicate that
 
1643
 * the information for all printers is desired.
 
1644
 */
 
1645
XpDiListEntry **
 
1646
XpDiGetPrinterList(
 
1647
    int nameLen,
 
1648
    char *name,
 
1649
    int localeLen,
 
1650
    char *locale)
 
1651
{
 
1652
    XpDiListEntry **pList;
 
1653
 
 
1654
    if(!nameLen || name == (char *)NULL)
 
1655
    {
 
1656
        int i;
 
1657
        PrinterDbPtr pDb;
 
1658
 
 
1659
        for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL; 
 
1660
            pDb = pDb->next, i++)
 
1661
            ;
 
1662
 
 
1663
        if((pList = (XpDiListEntry **)xalloc((i+1) * sizeof(XpDiListEntry *)))
 
1664
           == (XpDiListEntry **)NULL)
 
1665
            return pList;
 
1666
 
 
1667
        pList[i] = (XpDiListEntry *)NULL;
 
1668
        for(pDb = printerDb, i = 0; pDb != (PrinterDbPtr)NULL; 
 
1669
            pDb = pDb->next, i++)
 
1670
        {
 
1671
            if((pList[i] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry)))==
 
1672
               (XpDiListEntry *)NULL)
 
1673
            {
 
1674
                XpDiFreePrinterList(pList);
 
1675
                return (XpDiListEntry **)NULL;
 
1676
            }
 
1677
            FillPrinterListEntry(pList[i], pDb, localeLen, locale);
 
1678
        }
 
1679
    }
 
1680
    else
 
1681
    {
 
1682
        if((pList = (XpDiListEntry **)xalloc(2 * sizeof(XpDiListEntry *))) ==
 
1683
           (XpDiListEntry **)NULL)
 
1684
            return pList;
 
1685
 
 
1686
        if((pList[0] = (XpDiListEntry *)xalloc(sizeof(XpDiListEntry))) ==
 
1687
           (XpDiListEntry *)NULL)
 
1688
        {
 
1689
            xfree(pList);
 
1690
            return (XpDiListEntry **)NULL;
 
1691
        }
 
1692
        pList[1] = (XpDiListEntry *)NULL;
 
1693
        if(GetPrinterListInfo(pList[0], nameLen, name, localeLen, locale) == 
 
1694
           FALSE)
 
1695
        {
 
1696
            xfree(pList[0]);
 
1697
            pList[0] = (XpDiListEntry *)NULL;
 
1698
        }
 
1699
    }
 
1700
    return pList;
 
1701
}
 
1702
 
 
1703
WindowPtr
 
1704
XpDiValidatePrinter(char *printerName, int printerNameLen)
 
1705
{
 
1706
    PrinterDbPtr pCurEntry;
 
1707
 
 
1708
    for(pCurEntry = printerDb;
 
1709
        pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next)
 
1710
    {
 
1711
        if(strlen(pCurEntry->name) == (unsigned)printerNameLen &&
 
1712
           !strncmp(pCurEntry->name, printerName, printerNameLen))
 
1713
            return  WindowTable[pCurEntry->screenNum];
 
1714
    }
 
1715
    return (WindowPtr)NULL;
 
1716
}
 
1717
 
 
1718
/*
 
1719
 * XpDiGetDriverName takes a screen index and a printer name, and returns
 
1720
 * a pointer to the name of the driver to be used for the specified printer
 
1721
 * on the specified screen.
 
1722
 */
 
1723
char *
 
1724
XpDiGetDriverName(int index, char *printerName)
 
1725
{
 
1726
 
 
1727
    PrinterDbPtr pCurEntry;
 
1728
 
 
1729
    for(pCurEntry = printerDb;
 
1730
        pCurEntry != (PrinterDbPtr)NULL; pCurEntry = pCurEntry->next)
 
1731
    {
 
1732
        if(pCurEntry->screenNum == index &&
 
1733
           !strcmp(pCurEntry->name, printerName))
 
1734
            return pCurEntry->driverName;
 
1735
    }
 
1736
 
 
1737
    return (char *)NULL; /* XXX Should we supply a default driverName? */
 
1738
}