~ubuntu-branches/ubuntu/jaunty/texlive-bin/jaunty

« back to all changes in this revision

Viewing changes to build/TeX/texk/dvipsk/resident.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2008-06-26 23:14:59 UTC
  • mfrom: (2.1.30 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080626231459-y02rjsrgtafu83yr
Tags: 2007.dfsg.2-3
add missing source roadmap.fig of roadmap.eps in fontinst documentation
(Closes: #482915) (urgency medium due to RC bug)
(new patch add-missing-fontinst-source)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*   For use with emTeX set FONTPATH to "TEXTFM"
2
 
 */
3
 
#ifndef FONTPATH
4
 
#define FONTPATH "TEXFONTS"
5
 
#endif
6
 
 
7
 
/*
8
 
 *   This code reads in and handles the defaults for the program from the
9
 
 *   file config.sw.  This entire file is a bit kludgy, sorry.
10
 
 */
11
 
#include "dvips.h" /* The copyright notice in that file is included too! */
12
 
#include "paths.h"
13
 
#ifdef KPATHSEA
14
 
#include <kpathsea/c-ctype.h>
15
 
#include <kpathsea/c-pathch.h>
16
 
#include <kpathsea/c-stat.h>
17
 
#include <kpathsea/pathsearch.h>
18
 
#include <kpathsea/tex-file.h>
19
 
#include <kpathsea/variable.h>
20
 
#endif
21
 
/*
22
 
 *   This is the structure definition for resident fonts.  We use
23
 
 *   a small and simple hash table to handle these.  We don't need
24
 
 *   a big hash table.
25
 
 */
26
 
struct resfont *reshash[RESHASHPRIME] ;
27
 
/*
28
 
 *   These are the external routines we use.
29
 
 */
30
 
#include "protos.h"
31
 
/*
32
 
 *   These are the external variables we use.
33
 
 */
34
 
extern char *realnameoffile ;
35
 
#ifdef DEBUG
36
 
extern integer debug_flag;
37
 
#endif  /* DEBUG */
38
 
extern integer pagecopies ;
39
 
extern int overridemag ;
40
 
extern long bytesleft ;
41
 
extern quarterword *raster ;
42
 
extern FILE *pkfile ;
43
 
extern char *oname ;
44
 
extern integer swmem, fontmem ;
45
 
#ifndef KPATHSEA
46
 
extern char *tfmpath, *pictpath ;
47
 
extern char *pkpath ;
48
 
extern char *vfpath ;
49
 
extern char *figpath ;
50
 
extern char *configpath ;
51
 
extern char *headerpath ;
52
 
#ifdef SEARCH_SUBDIRECTORIES
53
 
extern char *fontsubdirpath ;
54
 
#endif
55
 
#endif
56
 
extern Boolean noenv ;
57
 
extern Boolean downloadpspk ;
58
 
#ifdef FONTLIB
59
 
extern char *flipath, *fliname ;
60
 
#endif
61
 
extern char *paperfmt ; 
62
 
extern char *nextstring ;
63
 
extern char *maxstring ;
64
 
extern char *warningmsg ;
65
 
extern Boolean disablecomments ;
66
 
extern Boolean compressed ;
67
 
extern Boolean partialdownload ;
68
 
extern int quiet ;
69
 
extern int filter ;
70
 
extern Boolean reverse ;
71
 
extern Boolean usesPSfonts ;
72
 
extern Boolean nosmallchars ;
73
 
extern Boolean removecomments ;
74
 
extern Boolean safetyenclose ;
75
 
extern Boolean dopprescan ;
76
 
extern integer maxsecsize ;
77
 
extern double mag ;
78
 
extern Boolean sepfiles ;
79
 
extern int actualdpi ;
80
 
extern int vactualdpi ;
81
 
extern int maxdrift ;
82
 
extern int vmaxdrift ;
83
 
extern char *printer ;
84
 
extern char *mfmode, *mflandmode ;
85
 
extern int mfmode_option;
86
 
extern int secure_option;
87
 
extern int oname_option;
88
 
extern Boolean sendcontrolD ;
89
 
#ifdef SHIFTLOWCHARS
90
 
extern Boolean shiftlowchars ;
91
 
#endif
92
 
extern unsigned lastresortsizes[] ;
93
 
extern integer hoff, voff ;
94
 
extern struct papsiz *papsizes ;
95
 
extern Boolean secure ;
96
 
extern integer hpapersize, vpapersize ;
97
 
extern int landscape ;
98
 
/*
99
 
 *   To maintain a list of document fonts, we use the following
100
 
 *   pointer.
101
 
 */
102
 
struct header_list *ps_fonts_used ;
103
 
/*
104
 
 *   Our hash routine.
105
 
 */
106
 
int
107
 
hash P1C(char *, s)
108
 
{
109
 
   int h = 12 ;
110
 
 
111
 
   while (*s != 0)
112
 
      h = (h + h + *s++) % RESHASHPRIME ;
113
 
   return(h) ;
114
 
}
115
 
/*
116
 
 *   Reverse the hash chains.
117
 
 */
118
 
void
119
 
revpslists P1H(void) {
120
 
   register int i ;
121
 
   for (i=0; i<RESHASHPRIME; i++)
122
 
      reshash[i] = (struct resfont *)revlist(reshash[i]) ;
123
 
}
124
 
/*
125
 
 *   cleanres() marks all resident fonts as not being yet sent, except
126
 
 *   those marked with 2 meaning they were downloaded as part of the
127
 
 *   main prolog (not section prolog).
128
 
 */
129
 
void
130
 
cleanres P1H(void) {
131
 
   register int i ;
132
 
   register struct resfont *p ;
133
 
   for (i=0; i<RESHASHPRIME; i++)
134
 
      for (p=reshash[i]; p; p=p->next)
135
 
         if (p->sent == 1)
136
 
            p->sent = 0 ;
137
 
}
138
 
/*
139
 
 *   The routine that looks up a font name.
140
 
 */
141
 
struct resfont *
142
 
lookup P1C(char *, name)
143
 
{
144
 
   struct resfont *p ;
145
 
 
146
 
   for (p=reshash[hash(name)]; p!=NULL; p=p->next)
147
 
      if (strcmp(p->Keyname, name)==0)
148
 
         return(p) ;
149
 
   return(NULL) ;
150
 
}
151
 
 
152
 
struct resfont *
153
 
findPSname P1C(char *, name)
154
 
{
155
 
   register int i ;
156
 
   register struct resfont *p ;
157
 
   for (i=0; i<RESHASHPRIME; i++)
158
 
      for (p=reshash[i]; p; p=p->next) {
159
 
         if (strcmp(p->PSname, name)==0)
160
 
            return p;
161
 
      }
162
 
   return NULL;
163
 
}
164
 
 
165
 
/*
166
 
 *   This routine adds an entry.
167
 
 */
168
 
void
169
 
add_entry P6C(char *, TeXname, char *, PSname, char *, Fontfile,
170
 
              char *, Vectfile, char *, specinfo, char *, downloadinfo)
171
 
{
172
 
   struct resfont *p ;
173
 
   int h ;
174
 
   if (PSname == NULL)
175
 
      PSname = TeXname ;
176
 
   p = (struct resfont *)mymalloc((integer)sizeof(struct resfont)) ;
177
 
   p->Keyname = TeXname ;
178
 
   p->PSname = PSname ;
179
 
   p->Fontfile = Fontfile;
180
 
   p->Vectfile = Vectfile;
181
 
   p->TeXname = TeXname ;
182
 
   p->specialinstructions = specinfo ;
183
 
   if (downloadinfo && *downloadinfo)
184
 
      p->downloadheader = downloadinfo ;
185
 
   else
186
 
      p->downloadheader = 0 ;
187
 
   h = hash(TeXname) ;
188
 
   p->next = reshash[h] ;
189
 
   p->sent = 0 ;
190
 
   reshash[h] = p ;
191
 
}
192
 
/*
193
 
 *   Now our residentfont routine.  Returns the number of characters in
194
 
 *   this font, based on the TFM file.
195
 
 */
196
 
extern char *infont ;
197
 
int
198
 
residentfont P1C(register fontdesctype *, curfnt)
199
 
{
200
 
   register shalfword i ;
201
 
   struct resfont *p ;
202
 
 
203
 
/*
204
 
 *   First we determine if we can find this font in the resident list.
205
 
 */
206
 
   if (*curfnt->area)
207
 
      return 0 ; /* resident fonts never have a nonstandard font area */
208
 
   if ((p=lookup(curfnt->name))==NULL)
209
 
      return 0 ;
210
 
/*
211
 
 *   This is not yet the correct way to do things, but it is useful as it
212
 
 *   is so we leave it in.  The problem:  if resident Times-Roman is
213
 
 *   re-encoded, then it will be downloaded as bitmaps; this is not
214
 
 *   right.  The solution will be to introduce two types of `<'
215
 
 *   directives, one that downloads fonts and one that downloads
216
 
 *   short headers that are innocuous.
217
 
 */
218
 
   if (p->Fontfile && downloadpspk) {
219
 
#ifdef DEBUG
220
 
      if (dd(D_FONTS))
221
 
         (void)fprintf(stderr,"Using PK font %s for <%s>.\n",
222
 
                                     curfnt->name, p->PSname) ;
223
 
#endif  /* DEBUG */
224
 
      return 0 ;
225
 
   }
226
 
/*
227
 
 *   We clear out some pointers:
228
 
 */
229
 
#ifdef DEBUG
230
 
   if (dd(D_FONTS))
231
 
        (void)fprintf(stderr,"Font %s <%s> is resident.\n",
232
 
                                     curfnt->name, p->PSname) ;
233
 
#endif  /* DEBUG */
234
 
   curfnt->resfont = p ;
235
 
   curfnt->name = p->TeXname ;
236
 
   for (i=0; i<256; i++) {
237
 
      curfnt->chardesc[i].TFMwidth = 0 ;
238
 
      curfnt->chardesc[i].packptr = NULL ;
239
 
      curfnt->chardesc[i].pixelwidth = 0 ;
240
 
      curfnt->chardesc[i].flags = 0 ;
241
 
      curfnt->chardesc[i].flags2 = 0 ;
242
 
   }
243
 
   add_name(p->PSname, &ps_fonts_used) ;
244
 
/*
245
 
 *   We include the font here.  But we only should need to include the
246
 
 *   font if we have a stupid spooler; smart spoolers should be able
247
 
 *   to supply it automatically.
248
 
 */
249
 
   if (p->downloadheader) {
250
 
      char *cp = p->downloadheader ;
251
 
      char *q ;
252
 
 
253
 
      infont = p->PSname ;
254
 
      while (1) {
255
 
         q = cp ;
256
 
         while (*cp && *cp != ' ')
257
 
            cp++ ;
258
 
         if (*cp) {
259
 
            *cp = 0 ;
260
 
            add_header(q) ;
261
 
            *cp++ = ' ' ;
262
 
         } else {
263
 
/*          if (strstr(q,".pfa")||strstr(q,".pfb")||
264
 
                strstr(q,".PFA")||strstr(q,".PFB"))
265
 
               break ;
266
 
            else */ {
267
 
              add_header(q) ;
268
 
              break;
269
 
            }
270
 
         }
271
 
         infont = 0 ;
272
 
      }
273
 
      infont = 0 ;
274
 
   }
275
 
   i = tfmload(curfnt) ;
276
 
   if (i < 0)
277
 
      i = 1 ;
278
 
   usesPSfonts = 1 ;
279
 
   return(i) ;
280
 
}
281
 
#define INLINE_SIZE (2000)
282
 
static char was_inline[INLINE_SIZE] ;
283
 
static unsigned c_lineno;
284
 
void
285
 
bad_config P1C(char *, err)
286
 
{
287
 
   fprintf (stderr, "%s:%d:", realnameoffile, c_lineno);
288
 
   error (err);
289
 
   fprintf(stderr, " (%s)\n", was_inline) ;
290
 
}
291
 
 
292
 
#ifndef KPATHSEA
293
 
/*
294
 
 *   Get environment variables! These override entries in ./config.h.
295
 
 *   We substitute everything of the form ::, ^: or :$ with default,
296
 
 *   so a user can easily build on to the existing paths.
297
 
 */
298
 
static char *getpath P2C(char *, who, char *, what)
299
 
{
300
 
   if (who) {
301
 
      register char *pp, *qq ;
302
 
      int lastsep = 1 ;
303
 
 
304
 
      for (pp=nextstring, qq=who; *qq;) {
305
 
         if (*qq == PATHSEP) {
306
 
            if (lastsep) {
307
 
               strcpy(pp, what) ;
308
 
               pp = pp + strlen(pp) ;
309
 
            }
310
 
            lastsep = 1 ;
311
 
         } else
312
 
            lastsep = 0 ;
313
 
         *pp++ = *qq++ ;
314
 
      }
315
 
      if (lastsep) {
316
 
         strcpy(pp, what) ;
317
 
         pp = pp + strlen(pp) ;
318
 
      }
319
 
      *pp = 0 ;
320
 
      qq = nextstring ;
321
 
      nextstring = pp + 1 ;
322
 
      return qq ;
323
 
   } else
324
 
      return what ;
325
 
}
326
 
#endif
327
 
/*
328
 
 *   We use this function so we can support strings delimited by
329
 
 *   double quotes with spaces in them.  We also accept strings
330
 
 *   with spaces in them, but kill off any spaces at the end.
331
 
 */
332
 
char *configstring P2C(char *, s, int, nullok)
333
 
{
334
 
   char tstr[INLINE_SIZE] ;
335
 
   char *p = tstr ;
336
 
 
337
 
   while (*s && *s <= ' ')
338
 
      s++ ;
339
 
   if (*s == '"') {
340
 
      s++ ;
341
 
      while (*s != 10 && *s != 0 && *s != '"' && p < tstr+290)
342
 
         *p++ = *s++ ;
343
 
   } else {
344
 
      while (*s && p < tstr+290)
345
 
         *p++ = *s++ ;
346
 
      while (*(p-1) <= ' ' && p > tstr)
347
 
         p-- ;
348
 
   }
349
 
   *p = 0 ;
350
 
   if (p == tstr && ! nullok)
351
 
      bad_config("bad string") ;
352
 
   return newstring(tstr) ;
353
 
}
354
 
#ifdef KPATHSEA
355
 
/* We use this in `getdefaults' to modify the kpathsea structure for the
356
 
   paths we read.  See kpathsea/tex-file.[ch].  */
357
 
#define SET_CLIENT_PATH(filefmt, val) \
358
 
  kpse_format_info[filefmt].client_path = xstrdup (val)
359
 
#endif
360
 
/*
361
 
 *   Now we have the getdefaults routine.
362
 
 */
363
 
char *psmapfile = PSMAPFILE ;
364
 
Boolean
365
 
getdefaults P1C(char *, s)
366
 
{
367
 
   FILE *deffile ;
368
 
   char PSname[INLINE_SIZE] ;
369
 
   register char *p ;
370
 
   integer hsiz, vsiz ;
371
 
#ifndef KPATHSEA
372
 
   char *d = configpath ;
373
 
   int i, j ;
374
 
#endif
375
 
   int canaddtopaper = 0 ;
376
 
 
377
 
   if (printer == NULL) {
378
 
      if (s) {
379
 
         strcpy(PSname, s) ;
380
 
      } else {
381
 
#ifdef KPATHSEA
382
 
         char *dvipsrc = kpse_var_value ("DVIPSRC");
383
 
#ifdef WIN32
384
 
         if (dvipsrc && *dvipsrc) {
385
 
           /* $DVIPSRC was set by user */
386
 
           strcpy(PSname, dvipsrc);
387
 
         }
388
 
         else 
389
 
           /* No env var, looking into some kind of standard path. */
390
 
           if (SearchPath(".;%HOME%;c:\\", ".dvipsrc", NULL,
391
 
                          INLINE_SIZE, PSname, 
392
 
                          &dvipsrc) == 0) {
393
 
             /* search failed, we must put something into PSname. */
394
 
             dvipsrc = kpse_var_expand(DVIPSRC);
395
 
             if (dvipsrc) {
396
 
               strcpy(PSname, dvipsrc);
397
 
               free(dvipsrc);
398
 
             }
399
 
             /* Else SearchPath has filled PSname with something */
400
 
           }
401
 
         /* remove any redundant path separators. Many configurations
402
 
            can show  up: c:\/.dvipsrc and so on ... */        
403
 
         { 
404
 
           char *p, *q;
405
 
           for (p = q = PSname; *p && (p - PSname < INLINE_SIZE) ; 
406
 
                p++, q++) {
407
 
             if (IS_DIR_SEP(*p)) {
408
 
               *q = DIR_SEP; p++; q++;
409
 
               while (*p && IS_DIR_SEP(*p)) p++;
410
 
             }
411
 
             *q = *p;
412
 
           }
413
 
           *q = '\0';
414
 
         }
415
 
#else
416
 
         if(!dvipsrc) dvipsrc = kpse_var_expand(DVIPSRC) ;
417
 
         strcpy(PSname, dvipsrc ? dvipsrc : "~/.dvipsrc") ;
418
 
         if(dvipsrc) free(dvipsrc) ;
419
 
#endif /* WIN32 */
420
 
         
421
 
#else /* ! KPATHSEA */
422
 
#ifndef VMCMS  /* IBM: VM/CMS - don't have home directory on VMCMS */
423
 
#ifndef MVSXA
424
 
         d = "~" ;
425
 
#endif
426
 
#endif  /* IBM: VM/CMS */
427
 
         strcpy(PSname, DVIPSRC) ;
428
 
#endif /* KPATHSEA */
429
 
      }
430
 
   } else {
431
 
#if defined(MSDOS) || defined(OS2)
432
 
      strcpy(PSname, printer) ;
433
 
      strcat(PSname, ".cfg") ;
434
 
#else
435
 
      strcpy(PSname, "config.") ;
436
 
      strcat(PSname, printer) ;
437
 
#endif
438
 
   }
439
 
#ifdef KPATHSEA
440
 
   if ((deffile=search(configpath,PSname,READ))!=NULL) {
441
 
#else
442
 
   if ((deffile=search(d,PSname,READ))!=NULL) {
443
 
#endif
444
 
#ifdef DEBUG
445
 
     if (dd (D_CONFIG)) {
446
 
       fprintf (stderr, "Reading dvips config file `%s':\n", realnameoffile);
447
 
     }
448
 
#endif
449
 
     c_lineno = 0;
450
 
     while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
451
 
       c_lineno++;
452
 
#ifdef DEBUG
453
 
       if (dd (D_CONFIG)) {
454
 
         fprintf (stderr, "%s:%d:%s", realnameoffile, c_lineno, was_inline);
455
 
       }
456
 
#endif
457
 
/*
458
 
 *   We need to get rid of the newline.
459
 
 */
460
 
       for (p=was_inline; *p; p++) ;
461
 
       while (p > was_inline && (*(p-1) == '\n' || *(p-1) == '\r')) {
462
 
          *--p = '\0' ;
463
 
       }
464
 
       if (was_inline[0] != '@')
465
 
          canaddtopaper = 0 ;
466
 
       switch (was_inline[0]) {
467
 
/*
468
 
 *   Handling paper size information:
469
 
 *
470
 
 *      If line is empty, then we clear out the paper size information
471
 
 *      we have so far.
472
 
 *
473
 
 *      If it is `@+', then we add to the current paper size info.
474
 
 *
475
 
 *      If it is `name hsize vsize', then we start a new definition.
476
 
 */
477
 
case '@' :
478
 
         p = was_inline + 1 ;
479
 
         while (*p && *p <= ' ') p++ ;
480
 
         if (*p == 0) {
481
 
            papsizes = 0 ; /* throw away memory */
482
 
         } else if (*p == '+') {
483
 
            if (canaddtopaper == 0)
484
 
               error(
485
 
      " @+ in config files must immediately following a @ lines") ;
486
 
            else {
487
 
               *(nextstring-1) = '\n' ;/* IBM: VM/CMS - changed 10 to "\n" */
488
 
               p++ ;
489
 
               while (*p && *p == ' ') p++ ;
490
 
               strcpy(nextstring, p) ;
491
 
               nextstring += strlen(p) + 1 ;
492
 
            }
493
 
         } else {
494
 
            struct papsiz *ps ;
495
 
            
496
 
            ps = (struct papsiz *)mymalloc((integer)sizeof(struct papsiz)) ;
497
 
            ps->next = papsizes ;
498
 
            papsizes = ps ;
499
 
            ps->name = p ;
500
 
            while (*p && *p > ' ')
501
 
               p++ ;
502
 
            *p++ = 0 ;
503
 
            ps->name = newstring(ps->name) ;
504
 
            while (*p && *p <= ' ') p++ ;
505
 
            handlepapersize(p, &hsiz, &vsiz) ;
506
 
            ps->xsize = hsiz ;
507
 
            ps->ysize = vsiz ;
508
 
            ps->specdat = nextstring++ ;
509
 
            *(ps->specdat) = 0 ;
510
 
            canaddtopaper = 1 ;
511
 
         }
512
 
         break ;
513
 
case 'a' :
514
 
         dopprescan = (was_inline[1] != '0') ;
515
 
         break ;
516
 
case 'b':
517
 
#ifdef SHORTINT
518
 
         if (sscanf(was_inline+1, "%ld", &pagecopies) != 1) 
519
 
           bad_config("missing pagecopies to b") ;
520
 
#else
521
 
         if (sscanf(was_inline+1, "%d", &pagecopies) != 1) 
522
 
           bad_config("missing pagecopies to b") ;
523
 
#endif
524
 
         if (pagecopies < 1 || pagecopies > 1000)
525
 
            bad_config("pagecopies not between 1 and 1000") ;
526
 
         break ;
527
 
case 'm' :
528
 
#ifdef SHORTINT
529
 
         if (sscanf(was_inline+1, "%ld", &swmem) != 1) 
530
 
           bad_config("missing swmem to m") ;
531
 
#else   /* ~SHORTINT */
532
 
         if (sscanf(was_inline+1, "%d", &swmem) != 1)
533
 
           bad_config("missing swmem to m") ;
534
 
#endif  /* ~SHORTINT */
535
 
         swmem += fontmem ; /* grab headers we've seen already */
536
 
         break ;
537
 
case 'M' :
538
 
         /* If the user specified a -mode, don't replace it.  */
539
 
         if (!mfmode_option)
540
 
           mfmode = configstring(was_inline+1, 0) ;
541
 
         mflandmode = 0 ;
542
 
         {
543
 
            char *pp ;
544
 
            for (pp=mfmode; pp && *pp>' '; pp++) ;
545
 
            if (pp && *pp == ' ') {
546
 
               *pp++ = 0 ;
547
 
               while (*pp && *pp <= ' ')
548
 
                  pp++ ;
549
 
               if (*pp)
550
 
                  mflandmode = pp ;
551
 
            }
552
 
         }
553
 
         break ;
554
 
case 'o' :
555
 
         if (!oname_option) {
556
 
           struct stat st_buf;
557
 
           oname = configstring(was_inline+1, 1) ;
558
 
           if ((*oname && oname[strlen(oname)-1] == ':')
559
 
               || (stat(oname, &st_buf) == 0 && S_ISCHR(st_buf.st_mode))) {
560
 
              sendcontrolD = 1 ; /* if we send to a device, *we* are spooler */
561
 
#if defined(MSDOS) || defined(OS2)
562
 
              oname[strlen(oname)-1] = 0 ;
563
 
#endif
564
 
           }
565
 
         }
566
 
         break ;
567
 
case 'F' :
568
 
         sendcontrolD = (was_inline[1] != '0') ;
569
 
         break ;
570
 
case 'O' :
571
 
         p = was_inline + 1 ;
572
 
         handlepapersize(p, &hoff, &voff) ;
573
 
         break ;
574
 
#ifdef FONTLIB
575
 
case 'L' : 
576
 
         {
577
 
            char tempname[INLINE_SIZE] ;
578
 
            extern char *fliparse() ;
579
 
            if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config("missing arg to L") ;
580
 
            else {
581
 
               flipath = getpath(fliparse(PSname,tempname), flipath);
582
 
               fliname = newstring(tempname) ;
583
 
            }
584
 
         }
585
 
         break ;
586
 
#endif
587
 
case 'T' : 
588
 
         if (sscanf(was_inline+1, "%s", PSname) != 1)
589
 
           bad_config("missing arg to T") ;
590
 
         else
591
 
#ifdef KPATHSEA
592
 
           SET_CLIENT_PATH (kpse_tfm_format, PSname);
593
 
#else
594
 
           tfmpath = getpath(PSname, tfmpath) ;
595
 
#endif
596
 
         break ;
597
 
case 'P' :
598
 
         if (sscanf(was_inline+1, "%s", PSname) != 1) bad_config("missing arg to P") ;
599
 
         else 
600
 
#ifdef KPATHSEA
601
 
           SET_CLIENT_PATH (kpse_pk_format, PSname);
602
 
#else
603
 
           pkpath = getpath(PSname, pkpath) ;
604
 
#endif
605
 
         break ;
606
 
case 'p' :
607
 
         p = was_inline + 1 ;
608
 
         while (*p && *p <= ' ')
609
 
            p++ ;
610
 
         if (*p == '+') {
611
 
            if (sscanf(p+1, "%s", PSname) != 1)
612
 
              bad_config("missing arg to p") ;
613
 
            getpsinfo(PSname) ;
614
 
         } else {
615
 
            psmapfile = configstring(was_inline+1, 0) ;
616
 
         }
617
 
         break ;
618
 
case 'v' : case 'V' :
619
 
         if (sscanf(was_inline+1, "%s", PSname) != 1) 
620
 
           bad_config("missing arg to V") ;
621
 
         else 
622
 
#ifdef KPATHSEA
623
 
           SET_CLIENT_PATH (kpse_vf_format, PSname);
624
 
#else
625
 
           vfpath = getpath(PSname, vfpath) ;
626
 
#endif
627
 
         break ;
628
 
case 'S' :
629
 
         if (sscanf(was_inline+1, "%s", PSname) != 1) 
630
 
           bad_config("missing arg to S") ;
631
 
         else
632
 
#ifdef KPATHSEA
633
 
           SET_CLIENT_PATH (kpse_pict_format, PSname);
634
 
#else
635
 
           figpath = getpath(PSname, figpath) ;
636
 
#endif
637
 
         break ;
638
 
case 's':
639
 
         safetyenclose = 1 ;
640
 
         break ;
641
 
case 'H' : 
642
 
         if (sscanf(was_inline+1, "%s", PSname) != 1) 
643
 
           bad_config("missing arg to H") ;
644
 
         else 
645
 
#ifdef KPATHSEA
646
 
           SET_CLIENT_PATH (headerpath, PSname);
647
 
#else
648
 
           headerpath = getpath(PSname, headerpath) ;
649
 
#endif
650
 
         break ;
651
 
case '%': case ' ' : case '*' : case '#' : case ';' :
652
 
case '=' : case 0 : case '\n' :
653
 
         break ;
654
 
case 'r' :
655
 
         reverse = (was_inline[1] != '0') ;
656
 
         break ;
657
 
/*
658
 
 *   This case is for last resort font scaling; I hate this, but enough
659
 
 *   people have in no uncertain terms demanded it that I'll go ahead and
660
 
 *   add it.
661
 
 *
662
 
 *   This line must have numbers on it, resolutions, to search for the
663
 
 *   font as a last resort, and then the font will be scaled.  These
664
 
 *   resolutions should be in increasing order.
665
 
 *
666
 
 *   For most machines, just `300' is sufficient here; on the NeXT,
667
 
 *   `300 400' may be more appropriate.
668
 
 */
669
 
case 'R':
670
 
#ifndef KPATHSEA
671
 
         i = 0 ;
672
 
         p = was_inline + 1 ;
673
 
         while (*p) {
674
 
            while (*p && *p <= ' ')
675
 
               p++ ;
676
 
            if ('0' <= *p && *p <= '9') {
677
 
               j = 0 ;
678
 
               while ('0' <= *p && *p <= '9')
679
 
                  j = 10 * j + (*p++ - '0') ;
680
 
               if (i > 0)
681
 
                  if (lastresortsizes[i-1] > j) {
682
 
                     bad_config("last resort sizes (R) must be sorted") ;
683
 
                  }
684
 
               lastresortsizes[i++] = j ;
685
 
            } else {
686
 
               if (*p == 0)
687
 
                  break ;
688
 
               bad_config("only numbers expected on `R' line") ;
689
 
            }
690
 
         }
691
 
         lastresortsizes[i] = 32000 ;
692
 
#else /* KPATHSEA */
693
 
         for (p = was_inline + 1; *p; p++) {
694
 
           if (isblank (*p)) {
695
 
             *p = ':';
696
 
           }
697
 
         }
698
 
         kpse_fallback_resolutions_string = xstrdup (was_inline + 1);
699
 
#endif
700
 
         break ;
701
 
case 'D' :
702
 
         if (sscanf(was_inline+1, "%d", &actualdpi) != 1)
703
 
           bad_config("missing arg to D") ;
704
 
         if (actualdpi < 10 || actualdpi > 10000)
705
 
           bad_config("dpi must be between 10 and 10000") ;
706
 
         vactualdpi = actualdpi;
707
 
         break ;
708
 
/*
709
 
 *   Execute a command.  This can be dangerous, but can also be very useful.
710
 
 */
711
 
case 'E' :
712
 
#ifdef SECURE
713
 
         error("dvips was compiled with SECURE, which disables E in config") ;
714
 
#else
715
 
         if (secure) {
716
 
            error("dvips -R option used, which disables E in config") ;
717
 
            break ;
718
 
         }
719
 
         (void)system(was_inline+1) ;
720
 
#endif
721
 
         break ;
722
 
case 'K':
723
 
         removecomments = (was_inline[1] != '0') ;
724
 
         break ;
725
 
case 'U':
726
 
         nosmallchars = (was_inline[1] != '0') ;
727
 
         break ;
728
 
case 'W':
729
 
         for (p=was_inline+1; *p && *p <= ' '; p++) ;
730
 
         if (*p)
731
 
            warningmsg = newstring(p) ;
732
 
         else
733
 
            warningmsg = 0 ;
734
 
         break ;
735
 
case 'X' :
736
 
         if (sscanf(was_inline+1, "%d", &actualdpi) != 1)
737
 
           bad_config("missing numeric arg to X") ;
738
 
         if (actualdpi < 10 || actualdpi > 10000)
739
 
           bad_config("X arg must be between 10 and 10000") ;
740
 
         break ;
741
 
case 'Y' :
742
 
         if (sscanf(was_inline+1, "%d", &vactualdpi) != 1)
743
 
           bad_config("missing numeric arg to Y") ;
744
 
         if (vactualdpi < 10 || vactualdpi > 10000)
745
 
           bad_config("Y arg must be between 10 and 10000") ;
746
 
         break ;
747
 
case 'x': case 'y':
748
 
         if (sscanf(was_inline+1, "%lg", &mag) != 1) 
749
 
           bad_config("missing arg to x or y") ;
750
 
         overridemag = (was_inline[0] == 'x') ? 1 : -1 ;
751
 
         break ;
752
 
case 'e' :
753
 
         if (sscanf(was_inline+1, "%d", &maxdrift) != 1)
754
 
           bad_config("missing arg to e") ;
755
 
         if (maxdrift < 0) bad_config("bad argument to e") ;
756
 
         vmaxdrift = maxdrift;
757
 
         break ;
758
 
case 'z' : 
759
 
         if (secure_option && secure && was_inline[1] == '0') {
760
 
           fprintf (stderr,
761
 
                    "warning: %s: z0 directive ignored since -R1 given\n",
762
 
                    realnameoffile);
763
 
         } else {
764
 
           secure = (was_inline[1] != '0') ;
765
 
         }
766
 
         break ;
767
 
case 'q' : case 'Q' :
768
 
         quiet = (was_inline[1] != '0') ;
769
 
         break ;
770
 
case 'f' :
771
 
         filter = (was_inline[1] != '0') ;
772
 
         if (filter)
773
 
           oname = "";
774
 
         /* noenv has already been tested, so no point in setting.  */
775
 
         sendcontrolD = 0;
776
 
         break ;
777
 
#ifdef SHIFTLOWCHARS
778
 
case 'G':
779
 
         shiftlowchars = (was_inline[1] != '0') ;
780
 
         break ;
781
 
#endif
782
 
case 'h' : 
783
 
         if (sscanf(was_inline+1, "%s", PSname) != 1)
784
 
           bad_config("missing arg to h") ;
785
 
         else (void)add_header(PSname) ;
786
 
         break ;
787
 
case 'i' :
788
 
         if (sscanf(was_inline+1, "%d", &maxsecsize) != 1)
789
 
            maxsecsize = 0 ;
790
 
         sepfiles = 1 ;
791
 
         break ;
792
 
case 'I':
793
 
         noenv = (was_inline[1] != '0') ;
794
 
         break ;
795
 
case 'N' :
796
 
         disablecomments = (was_inline[1] != '0') ;
797
 
         break ;
798
 
case 'Z' :
799
 
         compressed = (was_inline[1] != '0') ;
800
 
         break ;
801
 
case 'j':
802
 
         partialdownload = (was_inline[1] != '0') ;
803
 
         break ;
804
 
case 't' :
805
 
         if (sscanf(was_inline+1, "%s", PSname) != 1)
806
 
           bad_config("missing arg to t") ;
807
 
         else {
808
 
           if (strcmp(PSname, "landscape") == 0) {
809
 
               if (hpapersize || vpapersize)
810
 
                  error(
811
 
            "both landscape and papersize specified; ignoring landscape") ;
812
 
               else
813
 
                  landscape = 1 ;
814
 
            } else
815
 
               paperfmt = newstring(PSname) ;
816
 
         }
817
 
         break ;
818
 
default:
819
 
         bad_config("strange line") ;
820
 
      }
821
 
     }
822
 
     (void)fclose(deffile) ;
823
 
   } else {
824
 
      if (printer)
825
 
        {
826
 
          char msg[1000];
827
 
          sprintf (msg, "warning: no config file for `%s'", printer);
828
 
          error(msg);
829
 
          return 0;
830
 
        }
831
 
   }
832
 
  
833
 
  return 1;
834
 
}
835
 
 
836
 
/*
837
 
*   If a character pointer is passed in, use that name; else, use the
838
 
*   default (possibly set) name, psfonts.map.
839
 
*/
840
 
void getpsinfo P1C(char *, name)
841
 
{
842
 
    FILE *deffile ;
843
 
    register char *p ;
844
 
    char *specinfo, *downloadinfo ;
845
 
   char downbuf[500] ;
846
 
   char specbuf[500] ;
847
 
   int slen ;
848
 
 
849
 
   if (name == 0)
850
 
      name = psmapfile ;
851
 
   if ((deffile=search(mappath, name, READ))!=NULL) {
852
 
      while (fgets(was_inline, INLINE_SIZE, deffile)!=NULL) {
853
 
         p = was_inline ;
854
 
         if (*p > ' ' && *p != '*' && *p != '#' && *p != ';' && *p != '%') {
855
 
            char *TeXname = NULL ;
856
 
            char *PSname = NULL ;
857
 
            char *Fontfile = NULL;
858
 
            char *Vectfile = NULL;
859
 
            char *hdr_name = NULL;
860
 
            boolean nopartial_p = false;
861
 
            boolean encoding_p = false;
862
 
            specinfo = NULL ;
863
 
            downloadinfo = NULL ;
864
 
            downbuf[0] = 0 ;
865
 
            specbuf[0] = 0 ;
866
 
            while (*p) {
867
 
               encoding_p = false ;
868
 
               while (*p && *p <= ' ')
869
 
                  p++ ;
870
 
               if (*p) {
871
 
                  if (*p == '"') {             /* PostScript instructions? */
872
 
                     if (specinfo) {
873
 
                        strcat(specbuf, specinfo) ;
874
 
                        strcat(specbuf, " ") ;
875
 
                     }
876
 
                     specinfo = p + 1 ;
877
 
 
878
 
                  } else if (*p == '<') {    /* Header to download? */
879
 
                     /* If had previous downloadinfo, save it.  */
880
 
                     if (downloadinfo) {
881
 
                        strcat(downbuf, downloadinfo) ;
882
 
                        strcat(downbuf, " ") ;
883
 
                        downloadinfo = NULL;
884
 
                     }
885
 
                     if (p[1] == '<') {     /* << means always full download */
886
 
                       p++;
887
 
                       nopartial_p = true;
888
 
                     } else if (p[1] == '[') { /* <[ means an encoding */
889
 
                       p++;
890
 
                       encoding_p = true;
891
 
                     }
892
 
                     p++ ;
893
 
                     /* skip whitespace after < */
894
 
                     while (*p && *p <= ' ')
895
 
                       p++;
896
 
                     
897
 
                     /* save start of header name */
898
 
                     hdr_name = p ;
899
 
 
900
 
                  } else if (TeXname) /* second regular word on line? */
901
 
                     PSname = p ;
902
 
 
903
 
                  else                /* first regular word? */
904
 
                     TeXname = p ;
905
 
 
906
 
                  if (*p == '"') {
907
 
                     p++ ;            /* find end of "..." word */
908
 
                     while (*p != '"' && *p)
909
 
                        p++ ;
910
 
                  } else
911
 
                     while (*p > ' ') /* find end of anything else */
912
 
                        p++ ;
913
 
                  if (*p)
914
 
                     *p++ = 0 ;
915
 
 
916
 
                  /* If we had a header we were downloading, figure
917
 
                     out what to do; couldn't do this above since we
918
 
                     want to check the suffix.  */
919
 
                  if (hdr_name) {
920
 
                     char *suffix = find_suffix (hdr_name);
921
 
                     if (encoding_p || STREQ (suffix, "enc")) {
922
 
                        /* (SPQR) if it is a reencoding, pass on to
923
 
                           FontPart, and download as usual */
924
 
                        Vectfile = downloadinfo = hdr_name;
925
 
                     } else if (nopartial_p) {
926
 
                        downloadinfo = hdr_name ;
927
 
                     } else if  (FILESTRCASEEQ (suffix, "pfa")
928
 
                                 || FILESTRCASEEQ (suffix, "pfb")
929
 
                                 || STREQ (suffix, "PFA")
930
 
                                 || STREQ (suffix, "PFB")) {
931
 
                        Fontfile = hdr_name;
932
 
                     } else {
933
 
                        downloadinfo = hdr_name;
934
 
                     }
935
 
                  }
936
 
               }
937
 
            }
938
 
            if (specinfo)
939
 
               strcat(specbuf, specinfo) ;
940
 
            if (downloadinfo)
941
 
               strcat(downbuf, downloadinfo) ;
942
 
            slen = strlen(downbuf) - 1;
943
 
            if (downbuf[slen] == ' ') {
944
 
              downbuf[slen] = 0;
945
 
            }
946
 
            if (TeXname) {
947
 
               TeXname = newstring(TeXname) ;
948
 
               PSname = newstring(PSname) ;
949
 
               Fontfile = newstring(Fontfile);
950
 
               Vectfile = newstring(Vectfile);
951
 
               specinfo = newstring(specbuf) ;
952
 
               downloadinfo = newstring(downbuf) ;
953
 
               add_entry(TeXname, PSname, Fontfile, Vectfile,
954
 
                         specinfo, downloadinfo) ;
955
 
            }
956
 
         }
957
 
      }
958
 
      (void)fclose(deffile) ;
959
 
   }
960
 
   checkstrings() ;
961
 
}
962
 
#ifndef KPATHSEA
963
 
/*
964
 
 *   Get environment variables! These override entries in ./config.h.
965
 
 *   We substitute everything of the form ::, ^: or :$ with default,
966
 
 *   so a user can easily build on to the existing paths.
967
 
 */
968
 
static char *getenvup P2C(char *, who, char *, what)
969
 
{
970
 
   return getpath(getenv(who), what) ;
971
 
}
972
 
#endif
973
 
#if !defined(KPATHSEA) && defined(SEARCH_SUBDIRECTORIES)
974
 
static char *concat3();
975
 
#endif
976
 
void checkenv P1C(int, which)
977
 
{
978
 
#ifndef KPATHSEA
979
 
   if (which) {
980
 
      tfmpath = getenvup(FONTPATH, tfmpath) ;
981
 
      vfpath = getenvup("VFFONTS", vfpath) ;
982
 
      pictpath = getenvup("TEXPICTS", pictpath) ;
983
 
      figpath = getenvup("TEXINPUTS", figpath) ;
984
 
      headerpath = getenvup("DVIPSHEADERS", headerpath) ;
985
 
      if (getenv("TEXPKS"))
986
 
         pkpath = getenvup("TEXPKS", pkpath) ;
987
 
      else if (getenv("TEXPACKED"))
988
 
         pkpath = getenvup("TEXPACKED", pkpath) ;
989
 
      else if (getenv("PKFONTS"))
990
 
         pkpath = getenvup("PKFONTS", pkpath) ;
991
 
#ifdef SEARCH_SUBDIRECTORIES
992
 
      else if (getenv(FONTPATH))
993
 
         pkpath = getenvup(FONTPATH, pkpath) ;
994
 
      if (getenv ("TEXFONTS_SUBDIR"))
995
 
         fontsubdirpath = getenvup ("TEXFONTS_SUBDIR", fontsubdirpath);
996
 
      {
997
 
         char pathsep[2] ;
998
 
         char *do_subdir_path();
999
 
         char *dirs = do_subdir_path (fontsubdirpath);
1000
 
         /* If the paths were in dynamic storage before, that memory is
1001
 
            wasted now.  */
1002
 
         pathsep[0] = PATHSEP ;
1003
 
         pathsep[1] = '\0' ;
1004
 
         tfmpath = concat3 (tfmpath, pathsep, dirs);
1005
 
         pkpath = concat3 (pkpath, pathsep, dirs);
1006
 
      }
1007
 
#endif
1008
 
   } else
1009
 
      configpath = getenvup("TEXCONFIG", configpath) ;
1010
 
#endif
1011
 
}
1012
 
 
1013
 
#if !defined(KPATHSEA) && defined(SEARCH_SUBDIRECTORIES)
1014
 
 
1015
 
#include <sys/types.h>
1016
 
#include <sys/stat.h>
1017
 
#include <errno.h>
1018
 
 
1019
 
#ifdef SYSV
1020
 
#include <dirent.h>
1021
 
typedef struct dirent *directory_entry_type;
1022
 
#else
1023
 
#include <sys/dir.h>
1024
 
typedef struct direct *directory_entry_type;
1025
 
#endif
1026
 
 
1027
 
/* Declare the routine to get the current working directory.  */
1028
 
 
1029
 
#ifndef HAVE_GETCWD
1030
 
extern char *getwd ();
1031
 
#define getcwd(b, len)  ((b) ? getwd (b) : getwd (xmalloc (len)))
1032
 
#else
1033
 
#ifdef ANSI
1034
 
extern char *getcwd (char *, int);
1035
 
#else
1036
 
extern char *getcwd ();
1037
 
#endif /* not ANSI */
1038
 
#endif /* not HAVE_GETWD */
1039
 
 
1040
 
#if defined(SYSV) || defined(VMS) || defined(MSDOS) || defined(OS2) || defined(ATARIST)
1041
 
#define MAXPATHLEN (256)
1042
 
#else   /* ~SYSV */
1043
 
#include <sys/param.h>          /* for MAXPATHLEN */
1044
 
#endif
1045
 
 
1046
 
extern void exit() ;
1047
 
extern int chdir() ;
1048
 
 
1049
 
/* Memory operations: variants of malloc(3) and realloc(3) that just
1050
 
   give up the ghost when they fail.  */
1051
 
 
1052
 
char *
1053
 
xmalloc P1C(unsigned, size)
1054
 
{
1055
 
  char *mem = malloc (size);
1056
 
  
1057
 
  if (mem == NULL)
1058
 
    {
1059
 
      fprintf (stderr, "! Cannot allocate %u bytes.\n", size);
1060
 
      exit (10);
1061
 
    }
1062
 
  
1063
 
  return mem;
1064
 
}
1065
 
 
1066
 
 
1067
 
char *
1068
 
xrealloc P2C(char *, ptr, unsigned, size)
1069
 
{
1070
 
  char *mem = realloc (ptr, size);
1071
 
  
1072
 
  if (mem == NULL)
1073
 
    {
1074
 
      fprintf (stderr, "! Cannot reallocate %u bytes at %x.\n", size, (int)ptr);
1075
 
      exit (10);
1076
 
    }
1077
 
    
1078
 
  return mem;
1079
 
}
1080
 
 
1081
 
 
1082
 
/* Return, in NAME, the next component of PATH, i.e., the characters up
1083
 
   to the next PATHSEP.  */
1084
 
   
1085
 
static void
1086
 
next_component P2C(char *, name, char **, path)
1087
 
{
1088
 
  unsigned count = 0;
1089
 
  
1090
 
  while (**path != 0 && **path != PATHSEP)
1091
 
    {
1092
 
      name[count++] = **path;
1093
 
      (*path)++; /* Move further along, even between calls.  */
1094
 
    }
1095
 
  
1096
 
  name[count] = 0;
1097
 
  if (**path == PATHSEP)
1098
 
    (*path)++; /* Move past the delimiter.  */
1099
 
}
1100
 
 
1101
 
 
1102
 
#ifndef _POSIX_SOURCE
1103
 
#ifndef S_ISDIR
1104
 
#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
1105
 
#endif
1106
 
#endif
1107
 
 
1108
 
/* Return true if FN is a directory or a symlink to a directory,
1109
 
   false if not. */
1110
 
 
1111
 
int
1112
 
is_dir P1C(char *, fn)
1113
 
{
1114
 
  struct stat stats;
1115
 
 
1116
 
  return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
1117
 
}
1118
 
 
1119
 
 
1120
 
static char *
1121
 
concat3 P3C(char *, s1, char *, s2, char *, s3)
1122
 
{
1123
 
  char *r = xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
1124
 
  strcpy (r, s1);
1125
 
  strcat (r, s2);
1126
 
  strcat (r, s3);
1127
 
  return r;
1128
 
}
1129
 
 
1130
 
 
1131
 
/* DIR_LIST is the default list of directories (colon-separated) to
1132
 
   search.  We want to add all the subdirectories directly below each of
1133
 
   the directories in the path.
1134
 
     
1135
 
   We return the list of directories found.  */
1136
 
 
1137
 
char *
1138
 
do_subdir_path P1C(char *, dir_list)
1139
 
{
1140
 
  char *cwd;
1141
 
  unsigned len;
1142
 
  char *result = xmalloc ((unsigned)1);
1143
 
  char *temp = dir_list;
1144
 
  char dirsep[2] ;
1145
 
 
1146
 
  dirsep[0] = DIRSEP ;
1147
 
  dirsep[1] = '\0' ;
1148
 
 
1149
 
  /* Make a copy in writable memory.  */
1150
 
  dir_list = xmalloc (strlen (temp) + 1);
1151
 
  strcpy (dir_list, temp);
1152
 
  
1153
 
  *result = 0;
1154
 
 
1155
 
  /* Unfortunately, we can't look in the environment for the current
1156
 
     directory, because if we are running under a program (let's say
1157
 
     Emacs), the PWD variable might have been set by Emacs' parent
1158
 
     to the current directory at the time Emacs was invoked.  This
1159
 
     is not necessarily the same directory the user expects to be
1160
 
     in.  So, we must always call getcwd(3) or getwd(3), even though
1161
 
     they are slow and prone to hang in networked installations.  */
1162
 
  cwd = getcwd (NULL, MAXPATHLEN + 2);
1163
 
  if (cwd == NULL)
1164
 
    {
1165
 
      perror ("getcwd");
1166
 
      exit (errno);
1167
 
    }
1168
 
 
1169
 
  do
1170
 
    {
1171
 
      DIR *dir;
1172
 
      directory_entry_type e;
1173
 
      char dirname[MAXPATHLEN];
1174
 
 
1175
 
      next_component (dirname, &dir_list);
1176
 
 
1177
 
      /* All the `::'s should be gone by now, but we may as well make
1178
 
         sure `chdir' doesn't crash.  */
1179
 
      if (*dirname == 0) continue;
1180
 
 
1181
 
      /* By changing directories, we save a bunch of string
1182
 
         concatenations (and make the pathnames the kernel looks up
1183
 
         shorter).  */
1184
 
      if (chdir (dirname) != 0) continue;
1185
 
 
1186
 
      dir = opendir (".");
1187
 
      if (dir == NULL) continue;
1188
 
 
1189
 
      while ((e = readdir (dir)) != NULL)
1190
 
        {
1191
 
          if (is_dir (e->d_name) && strcmp (e->d_name, ".") != 0
1192
 
              && strcmp (e->d_name, "..") != 0)
1193
 
            {
1194
 
              char *found = concat3 (dirname, dirsep, e->d_name);
1195
 
 
1196
 
              result = xrealloc (result, strlen (result) + strlen (found) + 2);
1197
 
 
1198
 
              len = strlen (result);
1199
 
              if (len > 0)
1200
 
                {
1201
 
                  result[len] = PATHSEP;
1202
 
                  result[len + 1] = 0;
1203
 
                }
1204
 
              strcat (result, found);
1205
 
              free (found);
1206
 
            }
1207
 
        }
1208
 
      closedir (dir);
1209
 
 
1210
 
      /* Change back to the current directory, in case the path
1211
 
         contains relative directory names.  */
1212
 
      if (chdir (cwd) != 0)
1213
 
        {
1214
 
          perror (cwd);
1215
 
          exit (errno);
1216
 
        }
1217
 
    }
1218
 
  while (*dir_list != 0);
1219
 
  
1220
 
  return result;
1221
 
}
1222
 
#endif /* SEARCH_SUBDIRECTORIES */