xref: /plan9/sys/src/cmd/postscript/download/download.c (revision 4e3613ab15c331a9ada113286cc0f2a35bc0373d)
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 
53219b2ee8SDavid du Colombier #include <stdio.h>
54*4e3613abSDavid du Colombier #include <stdlib.h>
55*4e3613abSDavid du Colombier #include <unistd.h>
56*4e3613abSDavid du Colombier #include <fcntl.h>
57*4e3613abSDavid du Colombier #include <string.h>
58219b2ee8SDavid du Colombier #include <signal.h>
59219b2ee8SDavid du Colombier #include <sys/types.h>
60219b2ee8SDavid du Colombier #include <sys/stat.h>
61219b2ee8SDavid du Colombier 
62219b2ee8SDavid du Colombier #include "comments.h"			/* PostScript file structuring comments */
63219b2ee8SDavid du Colombier #include "gen.h"			/* general purpose definitions */
64219b2ee8SDavid du Colombier #include "path.h"			/* for temporary directory */
65219b2ee8SDavid du Colombier #include "ext.h"			/* external variable declarations */
66219b2ee8SDavid du Colombier #include "download.h"			/* a few special definitions */
67219b2ee8SDavid du Colombier 
68219b2ee8SDavid du Colombier char	*temp_dir = TEMPDIR;		/* temp directory - for copying stdin */
69219b2ee8SDavid du Colombier char	*hostfontdir = HOSTDIR;		/* host resident directory */
70219b2ee8SDavid du Colombier char	*mapname = "map";		/* map table - usually in *hostfontdir */
71219b2ee8SDavid du Colombier char	*suffix = "";			/* appended to the map table pathname */
72219b2ee8SDavid du Colombier Map	*map = NULL;			/* device font map table */
73219b2ee8SDavid du Colombier char	*stringspace = NULL;		/* for storing font and file strings */
74219b2ee8SDavid du Colombier int	next = 0;			/* next free slot in map[] */
75219b2ee8SDavid du Colombier 
76219b2ee8SDavid du Colombier char	*residentfonts = NULL;		/* list of printer resident fonts */
77219b2ee8SDavid du Colombier char	*printer = NULL;		/* printer name - only for Unix 4.0 lp */
78219b2ee8SDavid du Colombier 
79219b2ee8SDavid du Colombier char	buf[2048];			/* input file line buffer */
80219b2ee8SDavid du Colombier char	*comment = DOCUMENTFONTS;	/* look for this comment */
81219b2ee8SDavid du Colombier int	atend = FALSE;			/* TRUE only if a comment says so */
82219b2ee8SDavid du Colombier 
83219b2ee8SDavid du Colombier FILE	*fp_in = stdin;			/* next input file */
84219b2ee8SDavid du Colombier FILE	*fp_temp = NULL;		/* for copying stdin */
85219b2ee8SDavid du Colombier 
86219b2ee8SDavid du Colombier /*****************************************************************************/
87219b2ee8SDavid du Colombier 
88219b2ee8SDavid du Colombier main(agc, agv)
89219b2ee8SDavid du Colombier 
90219b2ee8SDavid du Colombier     int		agc;
91219b2ee8SDavid du Colombier     char	*agv[];
92219b2ee8SDavid du Colombier 
93219b2ee8SDavid du Colombier {
94219b2ee8SDavid du Colombier 
95219b2ee8SDavid du Colombier /*
96219b2ee8SDavid du Colombier  *
97219b2ee8SDavid du Colombier  * Host resident font downloader. The input files are assumed to be part of a
98219b2ee8SDavid du Colombier  * single PostScript job.
99219b2ee8SDavid du Colombier  *
100219b2ee8SDavid du Colombier  */
101219b2ee8SDavid du Colombier 
102219b2ee8SDavid du Colombier     argc = agc;				/* other routines may want them */
103219b2ee8SDavid du Colombier     argv = agv;
104219b2ee8SDavid du Colombier 
105219b2ee8SDavid du Colombier     prog_name = argv[0];		/* just for error messages */
106219b2ee8SDavid du Colombier 
107219b2ee8SDavid du Colombier     init_signals();			/* sets up interrupt handling */
108219b2ee8SDavid du Colombier     options();				/* first get command line options */
109219b2ee8SDavid du Colombier     readmap();				/* read the font map table */
110219b2ee8SDavid du Colombier     readresident();			/* and the optional resident font list */
111219b2ee8SDavid du Colombier     arguments();			/* then process non-option arguments */
112219b2ee8SDavid du Colombier     done();				/* and clean things up */
113219b2ee8SDavid du Colombier     exit(x_stat);			/* not much could be wrong */
114219b2ee8SDavid du Colombier 
115219b2ee8SDavid du Colombier }   /* End of main */
116219b2ee8SDavid du Colombier 
117219b2ee8SDavid du Colombier /*****************************************************************************/
118219b2ee8SDavid du Colombier 
119219b2ee8SDavid du Colombier init_signals()
120219b2ee8SDavid du Colombier 
121219b2ee8SDavid du Colombier {
122219b2ee8SDavid du Colombier 
123219b2ee8SDavid du Colombier /*
124219b2ee8SDavid du Colombier  *
125219b2ee8SDavid du Colombier  * Makes sure we handle interrupts properly.
126219b2ee8SDavid du Colombier  *
127219b2ee8SDavid du Colombier  */
128219b2ee8SDavid du Colombier 
129219b2ee8SDavid du Colombier     if ( signal(SIGINT, interrupt) == SIG_IGN ) {
130219b2ee8SDavid du Colombier 	signal(SIGINT, SIG_IGN);
131219b2ee8SDavid du Colombier 	signal(SIGQUIT, SIG_IGN);
132219b2ee8SDavid du Colombier 	signal(SIGHUP, SIG_IGN);
133219b2ee8SDavid du Colombier     } else {
134219b2ee8SDavid du Colombier 	signal(SIGHUP, interrupt);
135219b2ee8SDavid du Colombier 	signal(SIGQUIT, interrupt);
136219b2ee8SDavid du Colombier     }   /* End else */
137219b2ee8SDavid du Colombier 
138219b2ee8SDavid du Colombier     signal(SIGTERM, interrupt);
139219b2ee8SDavid du Colombier 
140219b2ee8SDavid du Colombier }   /* End of init_signals */
141219b2ee8SDavid du Colombier 
142219b2ee8SDavid du Colombier /*****************************************************************************/
143219b2ee8SDavid du Colombier 
144219b2ee8SDavid du Colombier options()
145219b2ee8SDavid du Colombier 
146219b2ee8SDavid du Colombier {
147219b2ee8SDavid du Colombier 
148219b2ee8SDavid du Colombier     int		ch;			/* return value from getopt() */
149219b2ee8SDavid du Colombier     char	*optnames = "c:fm:p:r:H:T:DI";
150219b2ee8SDavid du Colombier 
151219b2ee8SDavid du Colombier     extern char	*optarg;		/* used by getopt() */
152219b2ee8SDavid du Colombier     extern int	optind;
153219b2ee8SDavid du Colombier 
154219b2ee8SDavid du Colombier /*
155219b2ee8SDavid du Colombier  *
156219b2ee8SDavid du Colombier  * Reads and processes the command line options.
157219b2ee8SDavid du Colombier  *
158219b2ee8SDavid du Colombier  */
159219b2ee8SDavid du Colombier 
160219b2ee8SDavid du Colombier     while ( (ch = getopt(argc, argv, optnames)) != EOF ) {
161219b2ee8SDavid du Colombier 	switch ( ch ) {
162219b2ee8SDavid du Colombier 	    case 'c':			/* look for this comment */
163219b2ee8SDavid du Colombier 		    comment = optarg;
164219b2ee8SDavid du Colombier 		    break;
165219b2ee8SDavid du Colombier 
166219b2ee8SDavid du Colombier 	    case 'f':			/* force a complete input file scan */
167219b2ee8SDavid du Colombier 		    atend = TRUE;
168219b2ee8SDavid du Colombier 		    break;
169219b2ee8SDavid du Colombier 
170219b2ee8SDavid du Colombier 	    case 'm':			/* printer map table name */
171219b2ee8SDavid du Colombier 		    mapname = optarg;
172219b2ee8SDavid du Colombier 		    break;
173219b2ee8SDavid du Colombier 
174219b2ee8SDavid du Colombier 	    case 'p':			/* printer name - for Unix 4.0 lp */
175219b2ee8SDavid du Colombier 		    printer = optarg;
176219b2ee8SDavid du Colombier 		    break;
177219b2ee8SDavid du Colombier 
178219b2ee8SDavid du Colombier 	    case 'r':			/* resident font list */
179219b2ee8SDavid du Colombier 		    residentfonts = optarg;
180219b2ee8SDavid du Colombier 		    break;
181219b2ee8SDavid du Colombier 
182219b2ee8SDavid du Colombier 	    case 'H':			/* host resident font directory */
183219b2ee8SDavid du Colombier 		    hostfontdir = optarg;
184219b2ee8SDavid du Colombier 		    break;
185219b2ee8SDavid du Colombier 
186219b2ee8SDavid du Colombier 	    case 'T':			/* temporary file directory */
187219b2ee8SDavid du Colombier 		    temp_dir = optarg;
188219b2ee8SDavid du Colombier 		    break;
189219b2ee8SDavid du Colombier 
190219b2ee8SDavid du Colombier 	    case 'D':			/* debug flag */
191219b2ee8SDavid du Colombier 		    debug = ON;
192219b2ee8SDavid du Colombier 		    break;
193219b2ee8SDavid du Colombier 
194219b2ee8SDavid du Colombier 	    case 'I':			/* ignore FATAL errors */
195219b2ee8SDavid du Colombier 		    ignore = ON;
196219b2ee8SDavid du Colombier 		    break;
197219b2ee8SDavid du Colombier 
198219b2ee8SDavid du Colombier 	    case '?':			/* don't understand the option */
199219b2ee8SDavid du Colombier 		    error(FATAL, "");
200219b2ee8SDavid du Colombier 		    break;
201219b2ee8SDavid du Colombier 
202219b2ee8SDavid du Colombier 	    default:			/* don't know what to do for ch */
203219b2ee8SDavid du Colombier 		    error(FATAL, "missing case for option %c\n", ch);
204219b2ee8SDavid du Colombier 		    break;
205219b2ee8SDavid du Colombier 	}   /* End switch */
206219b2ee8SDavid du Colombier     }   /* End while */
207219b2ee8SDavid du Colombier 
208219b2ee8SDavid du Colombier     argc -= optind;			/* get ready for non-option args */
209219b2ee8SDavid du Colombier     argv += optind;
210219b2ee8SDavid du Colombier 
211219b2ee8SDavid du Colombier }   /* End of options */
212219b2ee8SDavid du Colombier 
213219b2ee8SDavid du Colombier /*****************************************************************************/
214219b2ee8SDavid du Colombier 
215219b2ee8SDavid du Colombier readmap()
216219b2ee8SDavid du Colombier 
217219b2ee8SDavid du Colombier {
218219b2ee8SDavid du Colombier 
219219b2ee8SDavid du Colombier     char	*path;
220219b2ee8SDavid du Colombier     char	*ptr;
221219b2ee8SDavid du Colombier     int		fd;
222219b2ee8SDavid du Colombier     struct stat	sbuf;
223219b2ee8SDavid du Colombier 
224219b2ee8SDavid du Colombier /*
225219b2ee8SDavid du Colombier  *
226219b2ee8SDavid du Colombier  * Initializes the map table by reading an ASCII mapping file. If mapname begins
227219b2ee8SDavid du Colombier  * with a / it's the map table. Otherwise hostfontdir, mapname, and suffix are
228219b2ee8SDavid du Colombier  * combined to build the final pathname. If we can open the file we read it all
229219b2ee8SDavid du Colombier  * into memory, erase comments, and separate the font and file name pairs. When
230219b2ee8SDavid du Colombier  * we leave next points to the next free slot in the map[] array. If it's zero
231219b2ee8SDavid du Colombier  * nothing was in the file or we couldn't open it.
232219b2ee8SDavid du Colombier  *
233219b2ee8SDavid du Colombier  */
234219b2ee8SDavid du Colombier 
235219b2ee8SDavid du Colombier     if ( hostfontdir == NULL || mapname == NULL )
236219b2ee8SDavid du Colombier 	return;
237219b2ee8SDavid du Colombier 
238219b2ee8SDavid du Colombier     if ( *mapname != '/' ) {
239*4e3613abSDavid du Colombier 	if ( (path = malloc(strlen(hostfontdir) + strlen(mapname) +
240219b2ee8SDavid du Colombier 						strlen(suffix) + 2)) == NULL )
241219b2ee8SDavid du Colombier 	    error(FATAL, "no memory");
242219b2ee8SDavid du Colombier 	sprintf(path, "%s/%s%s", hostfontdir, mapname, suffix);
243219b2ee8SDavid du Colombier     } else path = mapname;
244219b2ee8SDavid du Colombier 
245219b2ee8SDavid du Colombier     if ( (fd = open(path, 0)) != -1 ) {
246219b2ee8SDavid du Colombier 	if ( fstat(fd, &sbuf) == -1 )
247219b2ee8SDavid du Colombier 	    error(FATAL, "can't fstat %s", path);
248*4e3613abSDavid du Colombier 	if ( (stringspace = malloc(sbuf.st_size + 2)) == NULL )
249*4e3613abSDavid du Colombier 	    error(FATAL, "no memory for %s (%d bytes)", path, sbuf.st_size + 2);
250219b2ee8SDavid du Colombier 	if ( read(fd, stringspace, sbuf.st_size) == -1 )
251219b2ee8SDavid du Colombier 	    error(FATAL, "can't read %s", path);
252219b2ee8SDavid du Colombier 	close(fd);
253219b2ee8SDavid du Colombier 
254219b2ee8SDavid du Colombier 	stringspace[sbuf.st_size] = '\n';	/* just to be safe */
255219b2ee8SDavid du Colombier 	stringspace[sbuf.st_size+1] = '\0';
256219b2ee8SDavid du Colombier 	for ( ptr = stringspace; *ptr != '\0'; ptr++ )	/* erase comments */
257219b2ee8SDavid du Colombier 	    if ( *ptr == '%' )
258219b2ee8SDavid du Colombier 		for ( ; *ptr != '\n' ; ptr++ )
259219b2ee8SDavid du Colombier 		    *ptr = ' ';
260219b2ee8SDavid du Colombier 
261219b2ee8SDavid du Colombier 	for ( ptr = stringspace; ; next++ ) {
262219b2ee8SDavid du Colombier 	    if ( (next % 50) == 0 )
263219b2ee8SDavid du Colombier 		map = allocate(map, next+50);
264219b2ee8SDavid du Colombier 	    map[next].downloaded = FALSE;
265219b2ee8SDavid du Colombier 	    map[next].font = strtok(ptr, " \t\n");
266219b2ee8SDavid du Colombier 	    map[next].file = strtok(ptr = NULL, " \t\n");
267219b2ee8SDavid du Colombier 	    if ( map[next].font == NULL )
268219b2ee8SDavid du Colombier 		break;
269219b2ee8SDavid du Colombier 	    if ( map[next].file == NULL )
270219b2ee8SDavid du Colombier 		error(FATAL, "map table format error - check %s", path);
271219b2ee8SDavid du Colombier 	}   /* End for */
272219b2ee8SDavid du Colombier     }	/* End if */
273219b2ee8SDavid du Colombier 
274219b2ee8SDavid du Colombier }   /* End of readmap */
275219b2ee8SDavid du Colombier 
276219b2ee8SDavid du Colombier /*****************************************************************************/
277219b2ee8SDavid du Colombier 
278219b2ee8SDavid du Colombier readresident()
279219b2ee8SDavid du Colombier 
280219b2ee8SDavid du Colombier {
281219b2ee8SDavid du Colombier 
282219b2ee8SDavid du Colombier     FILE	*fp;
283219b2ee8SDavid du Colombier     char	*path;
284219b2ee8SDavid du Colombier     int		ch;
285219b2ee8SDavid du Colombier     int		n;
286219b2ee8SDavid du Colombier 
287219b2ee8SDavid du Colombier /*
288219b2ee8SDavid du Colombier  *
289219b2ee8SDavid du Colombier  * Reads a file that lists the resident fonts for a particular printer and marks
290219b2ee8SDavid du Colombier  * each font as already downloaded. Nothing's done if the file can't be read or
291219b2ee8SDavid du Colombier  * there's no mapping file. Comments, as in the map file, begin with a % and
292219b2ee8SDavid du Colombier  * extend to the end of the line. Added for Unix 4.0 lp.
293219b2ee8SDavid du Colombier  *
294219b2ee8SDavid du Colombier  */
295219b2ee8SDavid du Colombier 
296219b2ee8SDavid du Colombier     if ( next == 0 || (printer == NULL && residentfonts == NULL) )
297219b2ee8SDavid du Colombier 	return;
298219b2ee8SDavid du Colombier 
299219b2ee8SDavid du Colombier     if ( printer != NULL ) {		/* use Unix 4.0 lp pathnames */
30080ee5cbfSDavid du Colombier 	sprintf(buf, "%s/printers/%s", HOSTDIR, printer);
301219b2ee8SDavid du Colombier 	path = buf;
302219b2ee8SDavid du Colombier     } else path = residentfonts;
303219b2ee8SDavid du Colombier 
304219b2ee8SDavid du Colombier     if ( (fp = fopen(path, "r")) != NULL ) {
305219b2ee8SDavid du Colombier 	while ( fscanf(fp, "%s", buf) != EOF )
306219b2ee8SDavid du Colombier 	    if ( buf[0] == '%' )
307219b2ee8SDavid du Colombier 		while ( (ch = getc(fp)) != EOF && ch != '\n' ) ;
308219b2ee8SDavid du Colombier 	    else if ( (n = lookup(buf)) < next )
309219b2ee8SDavid du Colombier 		map[n].downloaded = TRUE;
310219b2ee8SDavid du Colombier 	fclose(fp);
311219b2ee8SDavid du Colombier     }	/* End if */
312219b2ee8SDavid du Colombier 
313219b2ee8SDavid du Colombier }   /* End of readresident */
314219b2ee8SDavid du Colombier 
315219b2ee8SDavid du Colombier /*****************************************************************************/
316219b2ee8SDavid du Colombier 
317219b2ee8SDavid du Colombier arguments()
318219b2ee8SDavid du Colombier 
319219b2ee8SDavid du Colombier {
320219b2ee8SDavid du Colombier 
321219b2ee8SDavid du Colombier /*
322219b2ee8SDavid du Colombier  *
323219b2ee8SDavid du Colombier  * Makes sure all the non-option command line arguments are processed. If we get
324219b2ee8SDavid du Colombier  * here and there aren't any arguments left, or if '-' is one of the input files
325219b2ee8SDavid du Colombier  * we'll translate stdin. Assumes input files are part of a single PostScript
326219b2ee8SDavid du Colombier  * job and fonts can be downloaded at the start of each file.
327219b2ee8SDavid du Colombier  *
328219b2ee8SDavid du Colombier  */
329219b2ee8SDavid du Colombier 
330219b2ee8SDavid du Colombier     if ( argc < 1 )
331219b2ee8SDavid du Colombier 	download();
332219b2ee8SDavid du Colombier     else {
333219b2ee8SDavid du Colombier 	while ( argc > 0 ) {
334219b2ee8SDavid du Colombier 	    fp_temp = NULL;
335219b2ee8SDavid du Colombier 	    if ( strcmp(*argv, "-") == 0 )
336219b2ee8SDavid du Colombier 		fp_in = stdin;
337219b2ee8SDavid du Colombier 	    else if ( (fp_in = fopen(*argv, "r")) == NULL )
338219b2ee8SDavid du Colombier 		error(FATAL, "can't open %s", *argv);
339219b2ee8SDavid du Colombier 	    download();
340219b2ee8SDavid du Colombier 	    if ( fp_in != stdin )
341219b2ee8SDavid du Colombier 		fclose(fp_in);
342219b2ee8SDavid du Colombier 	    if ( fp_temp != NULL )
343219b2ee8SDavid du Colombier 		fclose(fp_temp);
344219b2ee8SDavid du Colombier 	    argc--;
345219b2ee8SDavid du Colombier 	    argv++;
346219b2ee8SDavid du Colombier 	}   /* End while */
347219b2ee8SDavid du Colombier     }	/* End else */
348219b2ee8SDavid du Colombier 
349219b2ee8SDavid du Colombier }   /* End of arguments */
350219b2ee8SDavid du Colombier 
351219b2ee8SDavid du Colombier /*****************************************************************************/
352219b2ee8SDavid du Colombier 
353219b2ee8SDavid du Colombier done()
354219b2ee8SDavid du Colombier 
355219b2ee8SDavid du Colombier {
356219b2ee8SDavid du Colombier 
357219b2ee8SDavid du Colombier /*
358219b2ee8SDavid du Colombier  *
359219b2ee8SDavid du Colombier  * Clean things up before we quit.
360219b2ee8SDavid du Colombier  *
361219b2ee8SDavid du Colombier  */
362219b2ee8SDavid du Colombier 
363219b2ee8SDavid du Colombier     if ( temp_file != NULL )
364219b2ee8SDavid du Colombier 	unlink(temp_file);
365219b2ee8SDavid du Colombier 
366219b2ee8SDavid du Colombier }   /* End of done */
367219b2ee8SDavid du Colombier 
368219b2ee8SDavid du Colombier /*****************************************************************************/
369219b2ee8SDavid du Colombier 
370219b2ee8SDavid du Colombier download()
371219b2ee8SDavid du Colombier 
372219b2ee8SDavid du Colombier {
373219b2ee8SDavid du Colombier 
374219b2ee8SDavid du Colombier     int		infontlist = FALSE;
375219b2ee8SDavid du Colombier 
376219b2ee8SDavid du Colombier /*
377219b2ee8SDavid du Colombier  *
378219b2ee8SDavid du Colombier  * If next is zero the map table is empty and all we do is copy the input file
379219b2ee8SDavid du Colombier  * to stdout. Otherwise we read the input file looking for %%DocumentFonts: or
380219b2ee8SDavid du Colombier  * continuation comments, add any accessible fonts to the output file, and then
381219b2ee8SDavid du Colombier  * append the input file. When reading stdin we append lines to fp_temp and
382219b2ee8SDavid du Colombier  * recover them when we're ready to copy the input file. fp_temp will often
383219b2ee8SDavid du Colombier  * only contain part of stdin - if there's no %%DocumentFonts: (atend) comment
384219b2ee8SDavid du Colombier  * we stop reading fp_in after the header.
385219b2ee8SDavid du Colombier  *
386219b2ee8SDavid du Colombier  */
387219b2ee8SDavid du Colombier 
388219b2ee8SDavid du Colombier     if ( next > 0 ) {
389219b2ee8SDavid du Colombier 	if ( fp_in == stdin ) {
390219b2ee8SDavid du Colombier 	    if ( (temp_file = tempnam(temp_dir, "post")) == NULL )
391219b2ee8SDavid du Colombier 		error(FATAL, "can't generate temp file name");
392219b2ee8SDavid du Colombier 	    if ( (fp_temp = fopen(temp_file, "w+r")) == NULL )
393219b2ee8SDavid du Colombier 		error(FATAL, "can't open %s", temp_file);
394219b2ee8SDavid du Colombier 	    unlink(temp_file);
395219b2ee8SDavid du Colombier 	}   /* End if */
396219b2ee8SDavid du Colombier 
397219b2ee8SDavid du Colombier 	while ( fgets(buf, sizeof(buf), fp_in) != NULL ) {
398219b2ee8SDavid du Colombier 	    if ( fp_temp != NULL )
399219b2ee8SDavid du Colombier 		fprintf(fp_temp, "%s", buf);
400219b2ee8SDavid du Colombier 	    if ( buf[0] != '%' || buf[1] != '%' ) {
401219b2ee8SDavid du Colombier 		if ( (buf[0] != '%' || buf[1] != '!') && atend == FALSE )
402219b2ee8SDavid du Colombier 		    break;
403219b2ee8SDavid du Colombier 		infontlist = FALSE;
404219b2ee8SDavid du Colombier 	    } else if ( strncmp(buf, comment, strlen(comment)) == 0 ) {
405219b2ee8SDavid du Colombier 		copyfonts(buf);
406219b2ee8SDavid du Colombier 		infontlist = TRUE;
407219b2ee8SDavid du Colombier 	    } else if ( buf[2] == '+' && infontlist == TRUE )
408219b2ee8SDavid du Colombier 		copyfonts(buf);
409219b2ee8SDavid du Colombier 	    else infontlist = FALSE;
410219b2ee8SDavid du Colombier 	}   /* End while */
411219b2ee8SDavid du Colombier     }	/* End if */
412219b2ee8SDavid du Colombier 
413219b2ee8SDavid du Colombier     copyinput();
414219b2ee8SDavid du Colombier 
415219b2ee8SDavid du Colombier }   /* End of download */
416219b2ee8SDavid du Colombier 
417219b2ee8SDavid du Colombier /*****************************************************************************/
418219b2ee8SDavid du Colombier 
419219b2ee8SDavid du Colombier copyfonts(list)
420219b2ee8SDavid du Colombier 
421219b2ee8SDavid du Colombier     char	*list;
422219b2ee8SDavid du Colombier 
423219b2ee8SDavid du Colombier {
424219b2ee8SDavid du Colombier 
425219b2ee8SDavid du Colombier     char	*font;
426219b2ee8SDavid du Colombier     char	*path;
427219b2ee8SDavid du Colombier     int		n;
428219b2ee8SDavid du Colombier 
429219b2ee8SDavid du Colombier /*
430219b2ee8SDavid du Colombier  *
431219b2ee8SDavid du Colombier  * list points to a %%DocumentFonts: or continuation comment. What follows the
432219b2ee8SDavid du Colombier  * the keyword will be a list of fonts separated by white space (or (atend)).
433219b2ee8SDavid du Colombier  * Look for each font in the map table and if it's found copy the font file to
434219b2ee8SDavid du Colombier  * stdout (once only).
435219b2ee8SDavid du Colombier  *
436219b2ee8SDavid du Colombier  */
437219b2ee8SDavid du Colombier 
438219b2ee8SDavid du Colombier     strtok(list, " \n");		/* skip to the font list */
439219b2ee8SDavid du Colombier 
440219b2ee8SDavid du Colombier     while ( (font = strtok(NULL, " \t\n")) != NULL ) {
441219b2ee8SDavid du Colombier 	if ( strcmp(font, ATEND) == 0 ) {
442219b2ee8SDavid du Colombier 	    atend = TRUE;
443219b2ee8SDavid du Colombier 	    break;
444219b2ee8SDavid du Colombier 	}   /* End if */
445219b2ee8SDavid du Colombier 	if ( (n = lookup(font)) < next ) {
446219b2ee8SDavid du Colombier 	    if ( *map[n].file != '/' ) {
447*4e3613abSDavid du Colombier 		if ( (path = malloc(strlen(hostfontdir)+strlen(map[n].file)+2)) == NULL )
448219b2ee8SDavid du Colombier 		    error(FATAL, "no memory");
449219b2ee8SDavid du Colombier 		sprintf(path, "%s/%s", hostfontdir, map[n].file);
450219b2ee8SDavid du Colombier 		cat(path);
451219b2ee8SDavid du Colombier 		free(path);
452219b2ee8SDavid du Colombier 	    } else cat(map[n].file);
453219b2ee8SDavid du Colombier 	    map[n].downloaded = TRUE;
454219b2ee8SDavid du Colombier 	}   /* End if */
455219b2ee8SDavid du Colombier     }	/* End while */
456219b2ee8SDavid du Colombier 
457219b2ee8SDavid du Colombier }   /* End of copyfonts */
458219b2ee8SDavid du Colombier 
459219b2ee8SDavid du Colombier /*****************************************************************************/
460219b2ee8SDavid du Colombier 
461219b2ee8SDavid du Colombier copyinput()
462219b2ee8SDavid du Colombier 
463219b2ee8SDavid du Colombier {
464219b2ee8SDavid du Colombier 
465219b2ee8SDavid du Colombier /*
466219b2ee8SDavid du Colombier  *
467219b2ee8SDavid du Colombier  * Copies the input file to stdout. If fp_temp isn't NULL seek to the start and
468219b2ee8SDavid du Colombier  * add it to the output file - it's a partial (or complete) copy of stdin made
469219b2ee8SDavid du Colombier  * by download(). Then copy fp_in, but only seek to the start if it's not stdin.
470219b2ee8SDavid du Colombier  *
471219b2ee8SDavid du Colombier  */
472219b2ee8SDavid du Colombier 
473219b2ee8SDavid du Colombier     if ( fp_temp != NULL ) {
474219b2ee8SDavid du Colombier 	fseek(fp_temp, 0L, 0);
475219b2ee8SDavid du Colombier 	while ( fgets(buf, sizeof(buf), fp_temp) != NULL )
476219b2ee8SDavid du Colombier 	    printf("%s", buf);
477219b2ee8SDavid du Colombier     }	/* End if */
478219b2ee8SDavid du Colombier 
479219b2ee8SDavid du Colombier     if ( fp_in != stdin )
480219b2ee8SDavid du Colombier 	fseek(fp_in, 0L, 0);
481219b2ee8SDavid du Colombier 
482219b2ee8SDavid du Colombier     while ( fgets(buf, sizeof(buf), fp_in) != NULL )
483219b2ee8SDavid du Colombier 	printf("%s", buf);
484219b2ee8SDavid du Colombier 
485219b2ee8SDavid du Colombier }   /* End of copyinput */
486219b2ee8SDavid du Colombier 
487219b2ee8SDavid du Colombier /*****************************************************************************/
488219b2ee8SDavid du Colombier 
489219b2ee8SDavid du Colombier lookup(font)
490219b2ee8SDavid du Colombier 
491219b2ee8SDavid du Colombier     char	*font;
492219b2ee8SDavid du Colombier 
493219b2ee8SDavid du Colombier {
494219b2ee8SDavid du Colombier 
495219b2ee8SDavid du Colombier     int		i;
496219b2ee8SDavid du Colombier 
497219b2ee8SDavid du Colombier /*
498219b2ee8SDavid du Colombier  *
499219b2ee8SDavid du Colombier  * Looks for *font in the map table. Return the map table index if found and
500219b2ee8SDavid du Colombier  * not yet downloaded - otherwise return next.
501219b2ee8SDavid du Colombier  *
502219b2ee8SDavid du Colombier  */
503219b2ee8SDavid du Colombier 
504219b2ee8SDavid du Colombier     for ( i = 0; i < next; i++ )
505219b2ee8SDavid du Colombier 	if ( strcmp(font, map[i].font) == 0 ) {
506219b2ee8SDavid du Colombier 	    if ( map[i].downloaded == TRUE )
507219b2ee8SDavid du Colombier 		i = next;
508219b2ee8SDavid du Colombier 	    break;
509219b2ee8SDavid du Colombier 	}   /* End if */
510219b2ee8SDavid du Colombier 
511219b2ee8SDavid du Colombier     return(i);
512219b2ee8SDavid du Colombier 
513219b2ee8SDavid du Colombier }   /* End of lookup */
514219b2ee8SDavid du Colombier 
515219b2ee8SDavid du Colombier /*
516219b2ee8SDavid du Colombier  * Allocates space for num Map elements. Calls malloc() if ptr is NULL and
517219b2ee8SDavid du Colombier  * realloc() otherwise.
518219b2ee8SDavid du Colombier  */
519*4e3613abSDavid du Colombier Map *
520*4e3613abSDavid du Colombier allocate(Map *ptr, int num)
521*4e3613abSDavid du Colombier {
522219b2ee8SDavid du Colombier 	if (ptr == NULL)
523219b2ee8SDavid du Colombier 		ptr = (Map *)malloc(num * sizeof(Map));
524*4e3613abSDavid du Colombier 	else
525*4e3613abSDavid du Colombier 		ptr = (Map *)realloc(ptr, num * sizeof(Map));
526219b2ee8SDavid du Colombier 	if (ptr == NULL)
527219b2ee8SDavid du Colombier 		error(FATAL, "no map memory");
528*4e3613abSDavid du Colombier 	return ptr;
529*4e3613abSDavid du Colombier }
530