1219b2ee8SDavid du Colombier /*
2219b2ee8SDavid du Colombier * download - host resident font downloader
3219b2ee8SDavid du Colombier *
4219b2ee8SDavid du Colombier * Prepends host resident fonts to PostScript input files. The program assumes
5219b2ee8SDavid du Colombier * the input files are part of a single PostScript job and that requested fonts
6219b2ee8SDavid du Colombier * can be downloaded at the start of each input file. Downloaded fonts are the
7219b2ee8SDavid du Colombier * ones named in a %%DocumentFonts: comment and listed in a special map table.
8219b2ee8SDavid du Colombier * Map table pathnames (supplied using the -m option) that begin with a / are
9219b2ee8SDavid du Colombier * taken as is. Otherwise the final pathname is built using *hostfontdir (-H
10219b2ee8SDavid du Colombier * option), *mapname (-m option), and *suffix.
11219b2ee8SDavid du Colombier *
12219b2ee8SDavid du Colombier * The map table consists of fontname-filename pairs, separated by white space.
13219b2ee8SDavid du Colombier * Comments are introduced by % (as in PostScript) and extend to the end of the
14219b2ee8SDavid du Colombier * current line. The only fonts that can be downloaded are the ones listed in
15219b2ee8SDavid du Colombier * the active map table that point the program to a readable Unix file. A request
16219b2ee8SDavid du Colombier * for an unlisted font or inaccessible file is ignored. All font requests are
17219b2ee8SDavid du Colombier * ignored if the map table can't be read. In that case the program simply copies
18219b2ee8SDavid du Colombier * the input files to stdout.
19219b2ee8SDavid du Colombier *
20219b2ee8SDavid du Colombier * An example (but not one to follow) of what can be in a map table is,
21219b2ee8SDavid du Colombier *
22219b2ee8SDavid du Colombier * %
23219b2ee8SDavid du Colombier * % Map requests for Bookman-Light to file *hostfontdir/KR
24219b2ee8SDavid du Colombier * %
25219b2ee8SDavid du Colombier *
26219b2ee8SDavid du Colombier * Bookman-Light KR % Keeping everything (including the map
27219b2ee8SDavid du Colombier * % table) in *hostfontdir seems like the
28219b2ee8SDavid du Colombier * % cleanest approach.
29219b2ee8SDavid du Colombier *
30219b2ee8SDavid du Colombier * %
31219b2ee8SDavid du Colombier * % Map Palatino-Roman to file *hostfontdir/palatino/Roman
32219b2ee8SDavid du Colombier * %
33219b2ee8SDavid du Colombier * Palatino-Roman palatino/Roman
34219b2ee8SDavid du Colombier *
35219b2ee8SDavid du Colombier * % Map ZapfDingbats to file /usr/lib/host/dingbats
36219b2ee8SDavid du Colombier *
37219b2ee8SDavid du Colombier * ZapfDingbats /usr/lib/host/dingbats
38219b2ee8SDavid du Colombier *
39219b2ee8SDavid du Colombier * Once again, file names that begin with a / are taken as is. All others have
40219b2ee8SDavid du Colombier * *hostfontdir/ prepended to the file string associated with a particular font.
41219b2ee8SDavid du Colombier *
42219b2ee8SDavid du Colombier * Map table can be associated with a printer model (e.g. a LaserWriter), a
43219b2ee8SDavid du Colombier * printer destination, or whatever - the choice is up to an administrator.
44219b2ee8SDavid du Colombier * By destination may be best if your spooler is running several private
45219b2ee8SDavid du Colombier * printers. Host resident fonts are usually purchased under a license that
46219b2ee8SDavid du Colombier * restricts their use to a limited number of printers. A font licensed for
47219b2ee8SDavid du Colombier * a single printer should only be used on that printer.
48219b2ee8SDavid du Colombier *
49219b2ee8SDavid du Colombier * Was written quickly, so there's much room for improvement. Undoubtedly should
50219b2ee8SDavid du Colombier * be a more general program (e.g. scan for other comments).
51219b2ee8SDavid du Colombier */
52219b2ee8SDavid du Colombier
53*14f51593SDavid du Colombier #define _BSD_EXTENSION
54*14f51593SDavid du Colombier
55219b2ee8SDavid du Colombier #include <stdio.h>
564e3613abSDavid du Colombier #include <stdlib.h>
574e3613abSDavid du Colombier #include <unistd.h>
584e3613abSDavid du Colombier #include <fcntl.h>
594e3613abSDavid du Colombier #include <string.h>
60219b2ee8SDavid du Colombier #include <signal.h>
61219b2ee8SDavid du Colombier #include <sys/types.h>
62219b2ee8SDavid du Colombier #include <sys/stat.h>
63219b2ee8SDavid du Colombier
64219b2ee8SDavid du Colombier #include "comments.h" /* PostScript file structuring comments */
65219b2ee8SDavid du Colombier #include "gen.h" /* general purpose definitions */
66219b2ee8SDavid du Colombier #include "path.h" /* for temporary directory */
67219b2ee8SDavid du Colombier #include "ext.h" /* external variable declarations */
68219b2ee8SDavid du Colombier #include "download.h" /* a few special definitions */
69219b2ee8SDavid du Colombier
70219b2ee8SDavid du Colombier char *temp_dir = TEMPDIR; /* temp directory - for copying stdin */
71219b2ee8SDavid du Colombier char *hostfontdir = HOSTDIR; /* host resident directory */
72219b2ee8SDavid du Colombier char *mapname = "map"; /* map table - usually in *hostfontdir */
73219b2ee8SDavid du Colombier char *suffix = ""; /* appended to the map table pathname */
74219b2ee8SDavid du Colombier Map *map = NULL; /* device font map table */
75219b2ee8SDavid du Colombier char *stringspace = NULL; /* for storing font and file strings */
76219b2ee8SDavid du Colombier int next = 0; /* next free slot in map[] */
77219b2ee8SDavid du Colombier
78219b2ee8SDavid du Colombier char *residentfonts = NULL; /* list of printer resident fonts */
79219b2ee8SDavid du Colombier char *printer = NULL; /* printer name - only for Unix 4.0 lp */
80219b2ee8SDavid du Colombier
81219b2ee8SDavid du Colombier char buf[2048]; /* input file line buffer */
82219b2ee8SDavid du Colombier char *comment = DOCUMENTFONTS; /* look for this comment */
83219b2ee8SDavid du Colombier int atend = FALSE; /* TRUE only if a comment says so */
84219b2ee8SDavid du Colombier
85219b2ee8SDavid du Colombier FILE *fp_in = stdin; /* next input file */
86219b2ee8SDavid du Colombier FILE *fp_temp = NULL; /* for copying stdin */
87219b2ee8SDavid du Colombier
88*14f51593SDavid du Colombier void arguments(void);
89*14f51593SDavid du Colombier void copyfonts(char *);
90*14f51593SDavid du Colombier void copyinput(void);
91*14f51593SDavid du Colombier void done(void);
92*14f51593SDavid du Colombier void download(void);
93*14f51593SDavid du Colombier void init_signals(void);
94*14f51593SDavid du Colombier void options(void);
95*14f51593SDavid du Colombier void readmap(void);
96*14f51593SDavid du Colombier void readresident(void);
97219b2ee8SDavid du Colombier
main(agc,agv)98219b2ee8SDavid du Colombier main(agc, agv)
99219b2ee8SDavid du Colombier int agc;
100219b2ee8SDavid du Colombier char *agv[];
101219b2ee8SDavid du Colombier {
102219b2ee8SDavid du Colombier /*
103219b2ee8SDavid du Colombier *
104219b2ee8SDavid du Colombier * Host resident font downloader. The input files are assumed to be part of a
105219b2ee8SDavid du Colombier * single PostScript job.
106219b2ee8SDavid du Colombier *
107219b2ee8SDavid du Colombier */
108219b2ee8SDavid du Colombier
109219b2ee8SDavid du Colombier argc = agc; /* other routines may want them */
110219b2ee8SDavid du Colombier argv = agv;
111219b2ee8SDavid du Colombier
112219b2ee8SDavid du Colombier prog_name = argv[0]; /* just for error messages */
113219b2ee8SDavid du Colombier
114219b2ee8SDavid du Colombier init_signals(); /* sets up interrupt handling */
115219b2ee8SDavid du Colombier options(); /* first get command line options */
116219b2ee8SDavid du Colombier readmap(); /* read the font map table */
117219b2ee8SDavid du Colombier readresident(); /* and the optional resident font list */
118219b2ee8SDavid du Colombier arguments(); /* then process non-option arguments */
119219b2ee8SDavid du Colombier done(); /* and clean things up */
120219b2ee8SDavid du Colombier exit(x_stat); /* not much could be wrong */
121*14f51593SDavid du Colombier return 0;
122*14f51593SDavid du Colombier }
123219b2ee8SDavid du Colombier
124*14f51593SDavid du Colombier void
init_signals(void)125*14f51593SDavid du Colombier init_signals(void)
126219b2ee8SDavid du Colombier {
127219b2ee8SDavid du Colombier /*
128219b2ee8SDavid du Colombier * Makes sure we handle interrupts properly.
129219b2ee8SDavid du Colombier */
130219b2ee8SDavid du Colombier
131219b2ee8SDavid du Colombier if ( signal(SIGINT, interrupt) == SIG_IGN ) {
132219b2ee8SDavid du Colombier signal(SIGINT, SIG_IGN);
133219b2ee8SDavid du Colombier signal(SIGQUIT, SIG_IGN);
134219b2ee8SDavid du Colombier signal(SIGHUP, SIG_IGN);
135219b2ee8SDavid du Colombier } else {
136219b2ee8SDavid du Colombier signal(SIGHUP, interrupt);
137219b2ee8SDavid du Colombier signal(SIGQUIT, interrupt);
138*14f51593SDavid du Colombier }
139219b2ee8SDavid du Colombier
140219b2ee8SDavid du Colombier signal(SIGTERM, interrupt);
141*14f51593SDavid du Colombier }
142219b2ee8SDavid du Colombier
143*14f51593SDavid du Colombier void
options(void)144*14f51593SDavid du Colombier options(void)
145219b2ee8SDavid du Colombier {
146219b2ee8SDavid du Colombier int ch; /* return value from getopt() */
147219b2ee8SDavid du Colombier char *optnames = "c:fm:p:r:H:T:DI";
148219b2ee8SDavid du Colombier
149219b2ee8SDavid du Colombier extern char *optarg; /* used by getopt() */
150219b2ee8SDavid du Colombier extern int optind;
151219b2ee8SDavid du Colombier
152219b2ee8SDavid du Colombier /*
153219b2ee8SDavid du Colombier *
154219b2ee8SDavid du Colombier * Reads and processes the command line options.
155219b2ee8SDavid du Colombier *
156219b2ee8SDavid du Colombier */
157219b2ee8SDavid du Colombier
158219b2ee8SDavid du Colombier while ( (ch = getopt(argc, argv, optnames)) != EOF ) {
159219b2ee8SDavid du Colombier switch ( ch ) {
160219b2ee8SDavid du Colombier case 'c': /* look for this comment */
161219b2ee8SDavid du Colombier comment = optarg;
162219b2ee8SDavid du Colombier break;
163219b2ee8SDavid du Colombier
164219b2ee8SDavid du Colombier case 'f': /* force a complete input file scan */
165219b2ee8SDavid du Colombier atend = TRUE;
166219b2ee8SDavid du Colombier break;
167219b2ee8SDavid du Colombier
168219b2ee8SDavid du Colombier case 'm': /* printer map table name */
169219b2ee8SDavid du Colombier mapname = optarg;
170219b2ee8SDavid du Colombier break;
171219b2ee8SDavid du Colombier
172219b2ee8SDavid du Colombier case 'p': /* printer name - for Unix 4.0 lp */
173219b2ee8SDavid du Colombier printer = optarg;
174219b2ee8SDavid du Colombier break;
175219b2ee8SDavid du Colombier
176219b2ee8SDavid du Colombier case 'r': /* resident font list */
177219b2ee8SDavid du Colombier residentfonts = optarg;
178219b2ee8SDavid du Colombier break;
179219b2ee8SDavid du Colombier
180219b2ee8SDavid du Colombier case 'H': /* host resident font directory */
181219b2ee8SDavid du Colombier hostfontdir = optarg;
182219b2ee8SDavid du Colombier break;
183219b2ee8SDavid du Colombier
184219b2ee8SDavid du Colombier case 'T': /* temporary file directory */
185219b2ee8SDavid du Colombier temp_dir = optarg;
186219b2ee8SDavid du Colombier break;
187219b2ee8SDavid du Colombier
188219b2ee8SDavid du Colombier case 'D': /* debug flag */
189219b2ee8SDavid du Colombier debug = ON;
190219b2ee8SDavid du Colombier break;
191219b2ee8SDavid du Colombier
192219b2ee8SDavid du Colombier case 'I': /* ignore FATAL errors */
193219b2ee8SDavid du Colombier ignore = ON;
194219b2ee8SDavid du Colombier break;
195219b2ee8SDavid du Colombier
196219b2ee8SDavid du Colombier case '?': /* don't understand the option */
197219b2ee8SDavid du Colombier error(FATAL, "");
198219b2ee8SDavid du Colombier break;
199219b2ee8SDavid du Colombier
200219b2ee8SDavid du Colombier default: /* don't know what to do for ch */
201219b2ee8SDavid du Colombier error(FATAL, "missing case for option %c\n", ch);
202219b2ee8SDavid du Colombier break;
203219b2ee8SDavid du Colombier } /* End switch */
204219b2ee8SDavid du Colombier } /* End while */
205219b2ee8SDavid du Colombier
206219b2ee8SDavid du Colombier argc -= optind; /* get ready for non-option args */
207219b2ee8SDavid du Colombier argv += optind;
208*14f51593SDavid du Colombier }
209219b2ee8SDavid du Colombier
210*14f51593SDavid du Colombier void
readmap(void)211*14f51593SDavid du Colombier readmap(void)
212219b2ee8SDavid du Colombier {
213219b2ee8SDavid du Colombier char *path;
214219b2ee8SDavid du Colombier char *ptr;
215219b2ee8SDavid du Colombier int fd;
216219b2ee8SDavid du Colombier struct stat sbuf;
217219b2ee8SDavid du Colombier
218219b2ee8SDavid du Colombier /*
219219b2ee8SDavid du Colombier * Initializes the map table by reading an ASCII mapping file. If mapname begins
220219b2ee8SDavid du Colombier * with a / it's the map table. Otherwise hostfontdir, mapname, and suffix are
221219b2ee8SDavid du Colombier * combined to build the final pathname. If we can open the file we read it all
222219b2ee8SDavid du Colombier * into memory, erase comments, and separate the font and file name pairs. When
223219b2ee8SDavid du Colombier * we leave next points to the next free slot in the map[] array. If it's zero
224219b2ee8SDavid du Colombier * nothing was in the file or we couldn't open it.
225219b2ee8SDavid du Colombier */
226219b2ee8SDavid du Colombier
227219b2ee8SDavid du Colombier if ( hostfontdir == NULL || mapname == NULL )
228219b2ee8SDavid du Colombier return;
229219b2ee8SDavid du Colombier
230219b2ee8SDavid du Colombier if ( *mapname != '/' ) {
2314e3613abSDavid du Colombier if ( (path = malloc(strlen(hostfontdir) + strlen(mapname) +
232219b2ee8SDavid du Colombier strlen(suffix) + 2)) == NULL )
233219b2ee8SDavid du Colombier error(FATAL, "no memory");
234219b2ee8SDavid du Colombier sprintf(path, "%s/%s%s", hostfontdir, mapname, suffix);
235219b2ee8SDavid du Colombier } else path = mapname;
236219b2ee8SDavid du Colombier
237219b2ee8SDavid du Colombier if ( (fd = open(path, 0)) != -1 ) {
238219b2ee8SDavid du Colombier if ( fstat(fd, &sbuf) == -1 )
239219b2ee8SDavid du Colombier error(FATAL, "can't fstat %s", path);
2404e3613abSDavid du Colombier if ( (stringspace = malloc(sbuf.st_size + 2)) == NULL )
2414e3613abSDavid du Colombier error(FATAL, "no memory for %s (%d bytes)", path, sbuf.st_size + 2);
242219b2ee8SDavid du Colombier if ( read(fd, stringspace, sbuf.st_size) == -1 )
243219b2ee8SDavid du Colombier error(FATAL, "can't read %s", path);
244219b2ee8SDavid du Colombier close(fd);
245219b2ee8SDavid du Colombier
246219b2ee8SDavid du Colombier stringspace[sbuf.st_size] = '\n'; /* just to be safe */
247219b2ee8SDavid du Colombier stringspace[sbuf.st_size+1] = '\0';
248219b2ee8SDavid du Colombier for ( ptr = stringspace; *ptr != '\0'; ptr++ ) /* erase comments */
249219b2ee8SDavid du Colombier if ( *ptr == '%' )
250219b2ee8SDavid du Colombier for ( ; *ptr != '\n' ; ptr++ )
251219b2ee8SDavid du Colombier *ptr = ' ';
252219b2ee8SDavid du Colombier
253219b2ee8SDavid du Colombier for ( ptr = stringspace; ; next++ ) {
254219b2ee8SDavid du Colombier if ( (next % 50) == 0 )
255219b2ee8SDavid du Colombier map = allocate(map, next+50);
256219b2ee8SDavid du Colombier map[next].downloaded = FALSE;
257219b2ee8SDavid du Colombier map[next].font = strtok(ptr, " \t\n");
258219b2ee8SDavid du Colombier map[next].file = strtok(ptr = NULL, " \t\n");
259219b2ee8SDavid du Colombier if ( map[next].font == NULL )
260219b2ee8SDavid du Colombier break;
261219b2ee8SDavid du Colombier if ( map[next].file == NULL )
262219b2ee8SDavid du Colombier error(FATAL, "map table format error - check %s", path);
263*14f51593SDavid du Colombier }
264*14f51593SDavid du Colombier }
265*14f51593SDavid du Colombier }
266219b2ee8SDavid du Colombier
267*14f51593SDavid du Colombier void
readresident(void)268*14f51593SDavid du Colombier readresident(void)
269219b2ee8SDavid du Colombier {
270219b2ee8SDavid du Colombier FILE *fp;
271219b2ee8SDavid du Colombier char *path;
272219b2ee8SDavid du Colombier int ch;
273219b2ee8SDavid du Colombier int n;
274219b2ee8SDavid du Colombier
275219b2ee8SDavid du Colombier /*
276219b2ee8SDavid du Colombier * Reads a file that lists the resident fonts for a particular printer and marks
277219b2ee8SDavid du Colombier * each font as already downloaded. Nothing's done if the file can't be read or
278219b2ee8SDavid du Colombier * there's no mapping file. Comments, as in the map file, begin with a % and
279219b2ee8SDavid du Colombier * extend to the end of the line. Added for Unix 4.0 lp.
280219b2ee8SDavid du Colombier */
281219b2ee8SDavid du Colombier
282219b2ee8SDavid du Colombier if ( next == 0 || (printer == NULL && residentfonts == NULL) )
283219b2ee8SDavid du Colombier return;
284219b2ee8SDavid du Colombier
285219b2ee8SDavid du Colombier if ( printer != NULL ) { /* use Unix 4.0 lp pathnames */
28680ee5cbfSDavid du Colombier sprintf(buf, "%s/printers/%s", HOSTDIR, printer);
287219b2ee8SDavid du Colombier path = buf;
288219b2ee8SDavid du Colombier } else path = residentfonts;
289219b2ee8SDavid du Colombier
290219b2ee8SDavid du Colombier if ( (fp = fopen(path, "r")) != NULL ) {
291219b2ee8SDavid du Colombier while ( fscanf(fp, "%s", buf) != EOF )
292219b2ee8SDavid du Colombier if ( buf[0] == '%' )
293219b2ee8SDavid du Colombier while ( (ch = getc(fp)) != EOF && ch != '\n' ) ;
294219b2ee8SDavid du Colombier else if ( (n = lookup(buf)) < next )
295219b2ee8SDavid du Colombier map[n].downloaded = TRUE;
296219b2ee8SDavid du Colombier fclose(fp);
297*14f51593SDavid du Colombier }
298*14f51593SDavid du Colombier }
299219b2ee8SDavid du Colombier
300*14f51593SDavid du Colombier void
arguments(void)301*14f51593SDavid du Colombier arguments(void)
302219b2ee8SDavid du Colombier {
303219b2ee8SDavid du Colombier /*
304219b2ee8SDavid du Colombier *
305219b2ee8SDavid du Colombier * Makes sure all the non-option command line arguments are processed. If we get
306219b2ee8SDavid du Colombier * here and there aren't any arguments left, or if '-' is one of the input files
307219b2ee8SDavid du Colombier * we'll translate stdin. Assumes input files are part of a single PostScript
308219b2ee8SDavid du Colombier * job and fonts can be downloaded at the start of each file.
309219b2ee8SDavid du Colombier *
310219b2ee8SDavid du Colombier */
311219b2ee8SDavid du Colombier
312219b2ee8SDavid du Colombier if ( argc < 1 )
313219b2ee8SDavid du Colombier download();
314219b2ee8SDavid du Colombier else {
315219b2ee8SDavid du Colombier while ( argc > 0 ) {
316219b2ee8SDavid du Colombier fp_temp = NULL;
317219b2ee8SDavid du Colombier if ( strcmp(*argv, "-") == 0 )
318219b2ee8SDavid du Colombier fp_in = stdin;
319219b2ee8SDavid du Colombier else if ( (fp_in = fopen(*argv, "r")) == NULL )
320219b2ee8SDavid du Colombier error(FATAL, "can't open %s", *argv);
321219b2ee8SDavid du Colombier download();
322219b2ee8SDavid du Colombier if ( fp_in != stdin )
323219b2ee8SDavid du Colombier fclose(fp_in);
324219b2ee8SDavid du Colombier if ( fp_temp != NULL )
325219b2ee8SDavid du Colombier fclose(fp_temp);
326219b2ee8SDavid du Colombier argc--;
327219b2ee8SDavid du Colombier argv++;
328*14f51593SDavid du Colombier }
329*14f51593SDavid du Colombier }
330*14f51593SDavid du Colombier }
331219b2ee8SDavid du Colombier
332*14f51593SDavid du Colombier void
done(void)333*14f51593SDavid du Colombier done(void)
334219b2ee8SDavid du Colombier {
335219b2ee8SDavid du Colombier /*
336219b2ee8SDavid du Colombier * Clean things up before we quit.
337219b2ee8SDavid du Colombier */
338219b2ee8SDavid du Colombier if ( temp_file != NULL )
339219b2ee8SDavid du Colombier unlink(temp_file);
340*14f51593SDavid du Colombier }
341219b2ee8SDavid du Colombier
342*14f51593SDavid du Colombier void
download(void)343*14f51593SDavid du Colombier download(void)
344219b2ee8SDavid du Colombier {
345219b2ee8SDavid du Colombier int infontlist = FALSE;
346219b2ee8SDavid du Colombier
347219b2ee8SDavid du Colombier /*
348219b2ee8SDavid du Colombier *
349219b2ee8SDavid du Colombier * If next is zero the map table is empty and all we do is copy the input file
350219b2ee8SDavid du Colombier * to stdout. Otherwise we read the input file looking for %%DocumentFonts: or
351219b2ee8SDavid du Colombier * continuation comments, add any accessible fonts to the output file, and then
352219b2ee8SDavid du Colombier * append the input file. When reading stdin we append lines to fp_temp and
353219b2ee8SDavid du Colombier * recover them when we're ready to copy the input file. fp_temp will often
354219b2ee8SDavid du Colombier * only contain part of stdin - if there's no %%DocumentFonts: (atend) comment
355219b2ee8SDavid du Colombier * we stop reading fp_in after the header.
356219b2ee8SDavid du Colombier *
357219b2ee8SDavid du Colombier */
358219b2ee8SDavid du Colombier
359219b2ee8SDavid du Colombier if ( next > 0 ) {
360219b2ee8SDavid du Colombier if ( fp_in == stdin ) {
361219b2ee8SDavid du Colombier if ( (temp_file = tempnam(temp_dir, "post")) == NULL )
362219b2ee8SDavid du Colombier error(FATAL, "can't generate temp file name");
363219b2ee8SDavid du Colombier if ( (fp_temp = fopen(temp_file, "w+r")) == NULL )
364219b2ee8SDavid du Colombier error(FATAL, "can't open %s", temp_file);
365219b2ee8SDavid du Colombier unlink(temp_file);
366219b2ee8SDavid du Colombier } /* End if */
367219b2ee8SDavid du Colombier
368219b2ee8SDavid du Colombier while ( fgets(buf, sizeof(buf), fp_in) != NULL ) {
369219b2ee8SDavid du Colombier if ( fp_temp != NULL )
370219b2ee8SDavid du Colombier fprintf(fp_temp, "%s", buf);
371219b2ee8SDavid du Colombier if ( buf[0] != '%' || buf[1] != '%' ) {
372219b2ee8SDavid du Colombier if ( (buf[0] != '%' || buf[1] != '!') && atend == FALSE )
373219b2ee8SDavid du Colombier break;
374219b2ee8SDavid du Colombier infontlist = FALSE;
375219b2ee8SDavid du Colombier } else if ( strncmp(buf, comment, strlen(comment)) == 0 ) {
376219b2ee8SDavid du Colombier copyfonts(buf);
377219b2ee8SDavid du Colombier infontlist = TRUE;
378219b2ee8SDavid du Colombier } else if ( buf[2] == '+' && infontlist == TRUE )
379219b2ee8SDavid du Colombier copyfonts(buf);
380219b2ee8SDavid du Colombier else infontlist = FALSE;
381*14f51593SDavid du Colombier }
382*14f51593SDavid du Colombier }
383219b2ee8SDavid du Colombier copyinput();
384*14f51593SDavid du Colombier }
385219b2ee8SDavid du Colombier
386*14f51593SDavid du Colombier void
copyfonts(list)387219b2ee8SDavid du Colombier copyfonts(list)
388219b2ee8SDavid du Colombier char *list;
389219b2ee8SDavid du Colombier {
390219b2ee8SDavid du Colombier char *font;
391219b2ee8SDavid du Colombier char *path;
392219b2ee8SDavid du Colombier int n;
393219b2ee8SDavid du Colombier
394219b2ee8SDavid du Colombier /*
395219b2ee8SDavid du Colombier * list points to a %%DocumentFonts: or continuation comment. What follows the
396219b2ee8SDavid du Colombier * the keyword will be a list of fonts separated by white space (or (atend)).
397219b2ee8SDavid du Colombier * Look for each font in the map table and if it's found copy the font file to
398219b2ee8SDavid du Colombier * stdout (once only).
399219b2ee8SDavid du Colombier */
400219b2ee8SDavid du Colombier
401219b2ee8SDavid du Colombier strtok(list, " \n"); /* skip to the font list */
402219b2ee8SDavid du Colombier
403219b2ee8SDavid du Colombier while ( (font = strtok(NULL, " \t\n")) != NULL ) {
404219b2ee8SDavid du Colombier if ( strcmp(font, ATEND) == 0 ) {
405219b2ee8SDavid du Colombier atend = TRUE;
406219b2ee8SDavid du Colombier break;
407*14f51593SDavid du Colombier }
408219b2ee8SDavid du Colombier if ( (n = lookup(font)) < next ) {
409219b2ee8SDavid du Colombier if ( *map[n].file != '/' ) {
4104e3613abSDavid du Colombier if ( (path = malloc(strlen(hostfontdir)+strlen(map[n].file)+2)) == NULL )
411219b2ee8SDavid du Colombier error(FATAL, "no memory");
412219b2ee8SDavid du Colombier sprintf(path, "%s/%s", hostfontdir, map[n].file);
413219b2ee8SDavid du Colombier cat(path);
414219b2ee8SDavid du Colombier free(path);
415219b2ee8SDavid du Colombier } else cat(map[n].file);
416219b2ee8SDavid du Colombier map[n].downloaded = TRUE;
417*14f51593SDavid du Colombier }
418*14f51593SDavid du Colombier }
419*14f51593SDavid du Colombier }
420219b2ee8SDavid du Colombier
421*14f51593SDavid du Colombier void
copyinput(void)422*14f51593SDavid du Colombier copyinput(void)
423219b2ee8SDavid du Colombier {
424219b2ee8SDavid du Colombier /*
425219b2ee8SDavid du Colombier *
426219b2ee8SDavid du Colombier * Copies the input file to stdout. If fp_temp isn't NULL seek to the start and
427219b2ee8SDavid du Colombier * add it to the output file - it's a partial (or complete) copy of stdin made
428219b2ee8SDavid du Colombier * by download(). Then copy fp_in, but only seek to the start if it's not stdin.
429219b2ee8SDavid du Colombier *
430219b2ee8SDavid du Colombier */
431219b2ee8SDavid du Colombier
432219b2ee8SDavid du Colombier if ( fp_temp != NULL ) {
433219b2ee8SDavid du Colombier fseek(fp_temp, 0L, 0);
434219b2ee8SDavid du Colombier while ( fgets(buf, sizeof(buf), fp_temp) != NULL )
435219b2ee8SDavid du Colombier printf("%s", buf);
436219b2ee8SDavid du Colombier } /* End if */
437219b2ee8SDavid du Colombier
438219b2ee8SDavid du Colombier if ( fp_in != stdin )
439219b2ee8SDavid du Colombier fseek(fp_in, 0L, 0);
440219b2ee8SDavid du Colombier
441219b2ee8SDavid du Colombier while ( fgets(buf, sizeof(buf), fp_in) != NULL )
442219b2ee8SDavid du Colombier printf("%s", buf);
443*14f51593SDavid du Colombier }
444219b2ee8SDavid du Colombier
lookup(font)445219b2ee8SDavid du Colombier lookup(font)
446219b2ee8SDavid du Colombier char *font;
447219b2ee8SDavid du Colombier {
448219b2ee8SDavid du Colombier int i;
449219b2ee8SDavid du Colombier
450219b2ee8SDavid du Colombier /*
451219b2ee8SDavid du Colombier *
452219b2ee8SDavid du Colombier * Looks for *font in the map table. Return the map table index if found and
453219b2ee8SDavid du Colombier * not yet downloaded - otherwise return next.
454219b2ee8SDavid du Colombier *
455219b2ee8SDavid du Colombier */
456219b2ee8SDavid du Colombier
457219b2ee8SDavid du Colombier for ( i = 0; i < next; i++ )
458219b2ee8SDavid du Colombier if ( strcmp(font, map[i].font) == 0 ) {
459219b2ee8SDavid du Colombier if ( map[i].downloaded == TRUE )
460219b2ee8SDavid du Colombier i = next;
461219b2ee8SDavid du Colombier break;
462219b2ee8SDavid du Colombier } /* End if */
463219b2ee8SDavid du Colombier
464219b2ee8SDavid du Colombier return(i);
465219b2ee8SDavid du Colombier
466219b2ee8SDavid du Colombier } /* End of lookup */
467219b2ee8SDavid du Colombier
468219b2ee8SDavid du Colombier /*
469219b2ee8SDavid du Colombier * Allocates space for num Map elements. Calls malloc() if ptr is NULL and
470219b2ee8SDavid du Colombier * realloc() otherwise.
471219b2ee8SDavid du Colombier */
4724e3613abSDavid du Colombier Map *
allocate(Map * ptr,int num)4734e3613abSDavid du Colombier allocate(Map *ptr, int num)
4744e3613abSDavid du Colombier {
475219b2ee8SDavid du Colombier if (ptr == NULL)
476219b2ee8SDavid du Colombier ptr = (Map *)malloc(num * sizeof(Map));
4774e3613abSDavid du Colombier else
4784e3613abSDavid du Colombier ptr = (Map *)realloc(ptr, num * sizeof(Map));
479219b2ee8SDavid du Colombier if (ptr == NULL)
480219b2ee8SDavid du Colombier error(FATAL, "no map memory");
4814e3613abSDavid du Colombier return ptr;
4824e3613abSDavid du Colombier }
483