17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
227c478bdstevel@tonic-gate/*
23f928ce6ceastha * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bdstevel@tonic-gate * Use is subject to license terms.
257c478bdstevel@tonic-gate */
267c478bdstevel@tonic-gate
277c478bdstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bdstevel@tonic-gate/*	  All Rights Reserved  	*/
297c478bdstevel@tonic-gate
30f928ce6ceastha#pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bdstevel@tonic-gate
327c478bdstevel@tonic-gate/*
337c478bdstevel@tonic-gate *
347c478bdstevel@tonic-gate * download - host resident font downloader
357c478bdstevel@tonic-gate *
367c478bdstevel@tonic-gate * Prepends host resident fonts to PostScript input files. The program assumes
377c478bdstevel@tonic-gate * the input files are part of a single PostScript job and that requested fonts
387c478bdstevel@tonic-gate * can be downloaded at the start of each input file. Downloaded fonts are the
397c478bdstevel@tonic-gate * ones named in a %%DocumentFonts: comment and listed in a special map table.
407c478bdstevel@tonic-gate * Map table pathnames (supplied using the -m option) that begin with a / are
417c478bdstevel@tonic-gate * taken as is. Otherwise the final pathname is built using *hostfontdir (-H
427c478bdstevel@tonic-gate * option), *mapname (-m option), and *suffix.
437c478bdstevel@tonic-gate *
447c478bdstevel@tonic-gate * The map table consists of fontname-filename pairs, separated by white space.
457c478bdstevel@tonic-gate * Comments are introduced by % (as in PostScript) and extend to the end of the
467c478bdstevel@tonic-gate * current line. The only fonts that can be downloaded are the ones listed in
477c478bdstevel@tonic-gate * the active map table that point the program to a readable Unix file. A request
487c478bdstevel@tonic-gate * for an unlisted font or inaccessible file is ignored. All font requests are
497c478bdstevel@tonic-gate * ignored if the map table can't be read. In that case the program simply copies
507c478bdstevel@tonic-gate * the input files to stdout.
517c478bdstevel@tonic-gate *
527c478bdstevel@tonic-gate * An example (but not one to follow) of what can be in a map table is,
537c478bdstevel@tonic-gate *
547c478bdstevel@tonic-gate *	%
557c478bdstevel@tonic-gate *	% Map requests for Bookman-Light to file *hostfontdir/KR
567c478bdstevel@tonic-gate *	%
577c478bdstevel@tonic-gate *
587c478bdstevel@tonic-gate *	  Bookman-Light		KR	% Keeping everything (including the map
597c478bdstevel@tonic-gate *					% table) in *hostfontdir seems like the
607c478bdstevel@tonic-gate *					% cleanest approach.
617c478bdstevel@tonic-gate *
627c478bdstevel@tonic-gate *	%
637c478bdstevel@tonic-gate *	% Map Palatino-Roman to file *hostfontdir/palatino/Roman
647c478bdstevel@tonic-gate *	%
657c478bdstevel@tonic-gate *	  Palatino-Roman	palatino/Roman
667c478bdstevel@tonic-gate *
677c478bdstevel@tonic-gate *	% Map ZapfDingbats to file /usr/lib/host/dingbats
687c478bdstevel@tonic-gate *
697c478bdstevel@tonic-gate *	  ZapfDingbats		/usr/lib/host/dingbats
707c478bdstevel@tonic-gate *
717c478bdstevel@tonic-gate * Once again, file names that begin with a / are taken as is. All others have
727c478bdstevel@tonic-gate * *hostfontdir/ prepended to the file string associated with a particular font.
737c478bdstevel@tonic-gate *
747c478bdstevel@tonic-gate * Map table can be associated with a printer model (e.g. a LaserWriter), a
757c478bdstevel@tonic-gate * printer destination, or whatever - the choice is up to an administrator.
767c478bdstevel@tonic-gate * By destination may be best if your spooler is running several private
777c478bdstevel@tonic-gate * printers. Host resident fonts are usually purchased under a license that
787c478bdstevel@tonic-gate * restricts their use to a limited number of printers. A font licensed for
797c478bdstevel@tonic-gate * a single printer should only be used on that printer.
807c478bdstevel@tonic-gate *
817c478bdstevel@tonic-gate * Was written quickly, so there's much room for improvement. Undoubtedly should
827c478bdstevel@tonic-gate * be a more general program (e.g. scan for other comments).
837c478bdstevel@tonic-gate *
847c478bdstevel@tonic-gate */
857c478bdstevel@tonic-gate
867c478bdstevel@tonic-gate#include <stdio.h>
877c478bdstevel@tonic-gate#include <signal.h>
887c478bdstevel@tonic-gate#include <fcntl.h>
897c478bdstevel@tonic-gate#include <sys/types.h>
907c478bdstevel@tonic-gate#include <sys/stat.h>
917c478bdstevel@tonic-gate
927c478bdstevel@tonic-gate#include "comments.h"			/* PostScript file structuring comments */
937c478bdstevel@tonic-gate#include "gen.h"			/* general purpose definitions */
947c478bdstevel@tonic-gate#include "path.h"			/* for temporary directory */
957c478bdstevel@tonic-gate#include "ext.h"			/* external variable declarations */
967c478bdstevel@tonic-gate#include "download.h"			/* a few special definitions */
977c478bdstevel@tonic-gate
987c478bdstevel@tonic-gatechar	*temp_dir = TEMPDIR;		/* temp directory - for copying stdin */
997c478bdstevel@tonic-gatechar	*hostfontdir = HOSTFONTDIR;	/* host resident directory */
1007c478bdstevel@tonic-gatechar	*mapname = "map";		/* map table - usually in *hostfontdir */
1017c478bdstevel@tonic-gatechar	*suffix = "";			/* appended to the map table pathname */
1027c478bdstevel@tonic-gateMap	*map = NULL;			/* device font map table */
1037c478bdstevel@tonic-gatechar	*stringspace = NULL;		/* for storing font and file strings */
1047c478bdstevel@tonic-gateint	next = 0;			/* next free slot in map[] */
1057c478bdstevel@tonic-gate
1067c478bdstevel@tonic-gatechar	*residentfonts = NULL;		/* list of printer resident fonts */
1077c478bdstevel@tonic-gatechar	*printer = NULL;		/* printer name - only for Unix 4.0 lp */
1087c478bdstevel@tonic-gate
1097c478bdstevel@tonic-gatechar	buf[2048];			/* input file line buffer */
1107c478bdstevel@tonic-gatechar	*comment = DOCUMENTFONTS;	/* look for this comment */
1117c478bdstevel@tonic-gateint	atend = FALSE;			/* TRUE only if a comment says so */
1127c478bdstevel@tonic-gate
1137c478bdstevel@tonic-gateFILE	*fp_in = stdin;			/* next input file */
1147c478bdstevel@tonic-gateFILE	*fp_temp = NULL;		/* for copying stdin */
1157c478bdstevel@tonic-gate
116f928ce6ceasthastatic Map *allocate(Map *, int);
117f928ce6ceasthastatic void arguments(void);
118f928ce6ceasthastatic void copyfonts(char *);
119f928ce6ceasthastatic void copyinput(void);
120f928ce6ceasthastatic void done(void);
121f928ce6ceasthastatic void download(void);
122f928ce6ceasthastatic void init_signals(void);
123f928ce6ceasthastatic int lookup(char *);
124f928ce6ceasthastatic void options(void);
125f928ce6ceasthastatic void readmap(void);
126f928ce6ceasthastatic void readresident(void);
1277c478bdstevel@tonic-gate
128f928ce6ceastha/*****************************************************************************/
1297c478bdstevel@tonic-gate
130f928ce6ceasthaint
131f928ce6ceasthamain(int agc, char *agv[])
1327c478bdstevel@tonic-gate{
1337c478bdstevel@tonic-gate
1347c478bdstevel@tonic-gate/*
1357c478bdstevel@tonic-gate *
1367c478bdstevel@tonic-gate * Host resident font download. The input files are assumed to be part of a
1377c478bdstevel@tonic-gate * single PostScript job.
1387c478bdstevel@tonic-gate *
1397c478bdstevel@tonic-gate */
1407c478bdstevel@tonic-gate
1417c478bdstevel@tonic-gate    argc = agc;				/* other routines may want them */
1427c478bdstevel@tonic-gate    argv = agv;
1437c478bdstevel@tonic-gate
1447c478bdstevel@tonic-gate    prog_name = argv[0];		/* just for error messages */
1457c478bdstevel@tonic-gate
1467c478bdstevel@tonic-gate    init_signals();			/* sets up interrupt handling */
1477c478bdstevel@tonic-gate    options();				/* first get command line options */
1487c478bdstevel@tonic-gate    readmap();				/* read the font map table */
1497c478bdstevel@tonic-gate    readresident();			/* and the optional resident font list */
1507c478bdstevel@tonic-gate    arguments();			/* then process non-option arguments */
1517c478bdstevel@tonic-gate    done();				/* and clean things up */
1527c478bdstevel@tonic-gate
153f928ce6ceastha    return (x_stat);			/* not much could be wrong */
1547c478bdstevel@tonic-gate
1557c478bdstevel@tonic-gate}   /* End of main */
1567c478bdstevel@tonic-gate
1577c478bdstevel@tonic-gate/*****************************************************************************/
1587c478bdstevel@tonic-gate
159f928ce6ceasthastatic void
160f928ce6ceasthainit_signals(void)
1617c478bdstevel@tonic-gate{
1627c478bdstevel@tonic-gate    void	interrupt();		/* handles signals if we catching them */
1637c478bdstevel@tonic-gate
1647c478bdstevel@tonic-gate/*
1657c478bdstevel@tonic-gate *
1667c478bdstevel@tonic-gate * Makes sure we handle interrupts properly.
1677c478bdstevel@tonic-gate *
1687c478bdstevel@tonic-gate */
1697c478bdstevel@tonic-gate
1707c478bdstevel@tonic-gate    if ( signal(SIGINT, interrupt) == SIG_IGN )  {
1717c478bdstevel@tonic-gate	signal(SIGINT, SIG_IGN);
1727c478bdstevel@tonic-gate	signal(SIGQUIT, SIG_IGN);
1737c478bdstevel@tonic-gate	signal(SIGHUP, SIG_IGN);
1747c478bdstevel@tonic-gate    } else {
1757c478bdstevel@tonic-gate	signal(SIGHUP, interrupt);
1767c478bdstevel@tonic-gate	signal(SIGQUIT, interrupt);
1777c478bdstevel@tonic-gate    }   /* End else */
1787c478bdstevel@tonic-gate
1797c478bdstevel@tonic-gate    signal(SIGTERM, interrupt);
1807c478bdstevel@tonic-gate
1817c478bdstevel@tonic-gate}   /* End of init_signals */
1827c478bdstevel@tonic-gate
1837c478bdstevel@tonic-gate/*****************************************************************************/
1847c478bdstevel@tonic-gate
185f928ce6ceasthastatic void
186f928ce6ceasthaoptions(void)
1877c478bdstevel@tonic-gate{
1887c478bdstevel@tonic-gate
1897c478bdstevel@tonic-gate    int		ch;			/* return value from getopt() */
1907c478bdstevel@tonic-gate    char	*optnames = "c:fm:p:r:H:T:DI";
1917c478bdstevel@tonic-gate
1927c478bdstevel@tonic-gate    extern char	*optarg;		/* used by getopt() */
1937c478bdstevel@tonic-gate    extern int	optind;
1947c478bdstevel@tonic-gate
1957c478bdstevel@tonic-gate/*
1967c478bdstevel@tonic-gate *
1977c478bdstevel@tonic-gate * Reads and processes the command line options.
1987c478bdstevel@tonic-gate *
1997c478bdstevel@tonic-gate */
2007c478bdstevel@tonic-gate
2017c478bdstevel@tonic-gate    while ( (ch = getopt(argc, argv, optnames)) != EOF )  {
2027c478bdstevel@tonic-gate
2037c478bdstevel@tonic-gate	switch ( ch )  {
2047c478bdstevel@tonic-gate
2057c478bdstevel@tonic-gate	    case 'c':			/* look for this comment */
2067c478bdstevel@tonic-gate		    comment = optarg;
2077c478bdstevel@tonic-gate		    break;
2087c478bdstevel@tonic-gate
2097c478bdstevel@tonic-gate	    case 'f':			/* force a complete input file scan */
2107c478bdstevel@tonic-gate		    atend = TRUE;
2117c478bdstevel@tonic-gate		    break;
2127c478bdstevel@tonic-gate
2137c478bdstevel@tonic-gate	    case 'm':			/* printer map table name */
2147c478bdstevel@tonic-gate		    mapname = optarg;
2157c478bdstevel@tonic-gate		    break;
2167c478bdstevel@tonic-gate
2177c478bdstevel@tonic-gate	    case 'p':			/* printer name - for Unix 4.0 lp */
2187c478bdstevel@tonic-gate		    printer = optarg;
2197c478bdstevel@tonic-gate		    break;
2207c478bdstevel@tonic-gate
2217c478bdstevel@tonic-gate	    case 'r':			/* resident font list */
2227c478bdstevel@tonic-gate		    residentfonts = optarg;
2237c478bdstevel@tonic-gate		    break;
2247c478bdstevel@tonic-gate
2257c478bdstevel@tonic-gate	    case 'H':			/* host resident font directory */
2267c478bdstevel@tonic-gate		    hostfontdir = optarg;
2277c478bdstevel@tonic-gate		    break;
2287c478bdstevel@tonic-gate
2297c478bdstevel@tonic-gate	    case 'T':			/* temporary file directory */
2307c478bdstevel@tonic-gate		    temp_dir = optarg;
2317c478bdstevel@tonic-gate		    break;
2327c478bdstevel@tonic-gate
2337c478bdstevel@tonic-gate	    case 'D':			/* debug flag */
2347c478bdstevel@tonic-gate		    debug = ON;
2357c478bdstevel@tonic-gate		    break;
2367c478bdstevel@tonic-gate
2377c478bdstevel@tonic-gate	    case 'I':			/* ignore FATAL errors */
2387c478bdstevel@tonic-gate		    ignore = ON;
2397c478bdstevel@tonic-gate		    break;
2407c478bdstevel@tonic-gate
2417c478bdstevel@tonic-gate	    case '?':			/* don't understand the option */
2427c478bdstevel@tonic-gate		    error(FATAL, "");
2437c478bdstevel@tonic-gate		    break;
2447c478bdstevel@tonic-gate
2457c478bdstevel@tonic-gate	    default:			/* don't know what to do for ch */
2467c478bdstevel@tonic-gate		    error(FATAL, "missing case for option %c\n", ch);
2477c478bdstevel@tonic-gate		    break;
2487c478bdstevel@tonic-gate
2497c478bdstevel@tonic-gate	}   /* End switch */
2507c478bdstevel@tonic-gate
2517c478bdstevel@tonic-gate    }   /* End while */
2527c478bdstevel@tonic-gate
2537c478bdstevel@tonic-gate    argc -= optind;			/* get ready for non-option args */
2547c478bdstevel@tonic-gate    argv += optind;
2557c478bdstevel@tonic-gate
2567c478bdstevel@tonic-gate}   /* End of options */
2577c478bdstevel@tonic-gate
2587c478bdstevel@tonic-gate/*****************************************************************************/
2597c478bdstevel@tonic-gate
260f928ce6ceasthastatic void
261f928ce6ceasthareadmap(void)
2627c478bdstevel@tonic-gate{
2637c478bdstevel@tonic-gate    char	*path;
2647c478bdstevel@tonic-gate    char	*ptr;
2657c478bdstevel@tonic-gate    int		fd;
2667c478bdstevel@tonic-gate    struct stat	sbuf;
2677c478bdstevel@tonic-gate
2687c478bdstevel@tonic-gate/*
2697c478bdstevel@tonic-gate *
2707c478bdstevel@tonic-gate * Initializes the map table by reading an ASCII mapping file. If mapname begins
2717c478bdstevel@tonic-gate * with a / it's the map table. Otherwise hostfontdir, mapname, and suffix are
2727c478bdstevel@tonic-gate * combined to build the final pathname. If we can open the file we read it all
2737c478bdstevel@tonic-gate * into memory, erase comments, and separate the font and file name pairs. When
2747c478bdstevel@tonic-gate * we leave next points to the next free slot in the map[] array. If it's zero
2757c478bdstevel@tonic-gate * nothing was in the file or we couldn't open it.
2767c478bdstevel@tonic-gate *
2777c478bdstevel@tonic-gate */
2787c478bdstevel@tonic-gate
2797c478bdstevel@tonic-gate    if ( hostfontdir == NULL || mapname == NULL )
2807c478bdstevel@tonic-gate	return;
2817c478bdstevel@tonic-gate
2827c478bdstevel@tonic-gate    if ( *mapname != '/' ) {
2837c478bdstevel@tonic-gate	if ( (path = malloc(strlen(hostfontdir) + strlen(mapname) +
2847c478bdstevel@tonic-gate						strlen(suffix) + 2)) == NULL )
2857c478bdstevel@tonic-gate	    error(FATAL, "no memory");
2867c478bdstevel@tonic-gate	sprintf(path, "%s/%s%s", hostfontdir, mapname, suffix);
2877c478bdstevel@tonic-gate    } else path = mapname;
2887c478bdstevel@tonic-gate
2897c478bdstevel@tonic-gate    if ( (fd = open(path, 0)) != -1 ) {
2907c478bdstevel@tonic-gate	if ( fstat(fd, &sbuf) == -1 )
2917c478bdstevel@tonic-gate	    error(FATAL, "can't fstat %s", path);
2927c478bdstevel@tonic-gate	if ( (stringspace = malloc(sbuf.st_size + 2)) == NULL )
2937c478bdstevel@tonic-gate	    error(FATAL, "no memory");
2947c478bdstevel@tonic-gate	if ( read(fd, stringspace, sbuf.st_size) == -1 )
2957c478bdstevel@tonic-gate	    error(FATAL, "can't read %s", path);
2967c478bdstevel@tonic-gate	close(fd);
2977c478bdstevel@tonic-gate
2987c478bdstevel@tonic-gate	stringspace[sbuf.st_size] = '\n';	/* just to be safe */
2997c478bdstevel@tonic-gate	stringspace[sbuf.st_size+1] = '\0';
3007c478bdstevel@tonic-gate	for ( ptr = stringspace; *ptr != '\0'; ptr++ )	/* erase comments */
3017c478bdstevel@tonic-gate	    if ( *ptr == '%' )
3027c478bdstevel@tonic-gate		for ( ; *ptr != '\n' ; ptr++ )
3037c478bdstevel@tonic-gate		    *ptr = ' ';
3047c478bdstevel@tonic-gate
3057c478bdstevel@tonic-gate	for ( ptr = stringspace; ; next++ ) {
3067c478bdstevel@tonic-gate	    if ( (next % 50) == 0 )
3077c478bdstevel@tonic-gate		map = allocate(map, next+50);
3087c478bdstevel@tonic-gate	    map[next].downloaded = FALSE;
3097c478bdstevel@tonic-gate	    map[next].font = strtok(ptr, " \t\n");
3107c478bdstevel@tonic-gate	    map[next].file = strtok(ptr = NULL, " \t\n");
3117c478bdstevel@tonic-gate	    if ( map[next].font == NULL )
3127c478bdstevel@tonic-gate		break;
3137c478bdstevel@tonic-gate	    if ( map[next].file == NULL )
3147c478bdstevel@tonic-gate		error(FATAL, "map table format error - check %s", path);
3157c478bdstevel@tonic-gate	}   /* End for */
3167c478bdstevel@tonic-gate    }	/* End if */
3177c478bdstevel@tonic-gate
3187c478bdstevel@tonic-gate}   /* End of readmap */
3197c478bdstevel@tonic-gate
3207c478bdstevel@tonic-gate/*****************************************************************************/
3217c478bdstevel@tonic-gate
322f928ce6ceasthastatic void
323f928ce6ceasthareadresident(void)
3247c478bdstevel@tonic-gate{
3257c478bdstevel@tonic-gate    FILE	*fp;
3267c478bdstevel@tonic-gate    char	*path;
3277c478bdstevel@tonic-gate    int		ch;
3287c478bdstevel@tonic-gate    int		n;
3297c478bdstevel@tonic-gate
3307c478bdstevel@tonic-gate/*
3317c478bdstevel@tonic-gate *
3327c478bdstevel@tonic-gate * Reads a file that lists the resident fonts for a particular printer and marks
3337c478bdstevel@tonic-gate * each font as already downloaded. Nothing's done if the file can't be read or
3347c478bdstevel@tonic-gate * there's no mapping file. Comments, as in the map file, begin with a % and
3357c478bdstevel@tonic-gate * extend to the end of the line. Added for Unix 4.0 lp.
3367c478bdstevel@tonic-gate *
3377c478bdstevel@tonic-gate */
3387c478bdstevel@tonic-gate
3397c478bdstevel@tonic-gate    if ( next == 0 || (printer == NULL && residentfonts == NULL) )
3407c478bdstevel@tonic-gate	return;
3417c478bdstevel@tonic-gate
3427c478bdstevel@tonic-gate    if ( printer != NULL ) {		/* use Unix 4.0 lp pathnames */
3437c478bdstevel@tonic-gate	sprintf(buf, "/etc/lp/printers/%s/residentfonts", printer);
3447c478bdstevel@tonic-gate	path = buf;
3457c478bdstevel@tonic-gate    } else path = residentfonts;
3467c478bdstevel@tonic-gate
3477c478bdstevel@tonic-gate    if ( (fp = fopen(path, "r")) != NULL ) {
3487c478bdstevel@tonic-gate	while ( fscanf(fp, "%s", buf) != EOF )
3497c478bdstevel@tonic-gate	    if ( buf[0] == '%' )
3507c478bdstevel@tonic-gate		while ( (ch = getc(fp)) != EOF && ch != '\n' ) ;
3517c478bdstevel@tonic-gate	    else if ( (n = lookup(buf)) < next )
3527c478bdstevel@tonic-gate		map[n].downloaded = TRUE;
3537c478bdstevel@tonic-gate	fclose(fp);
3547c478bdstevel@tonic-gate    }	/* End if */
3557c478bdstevel@tonic-gate
3567c478bdstevel@tonic-gate}   /* End of readresident */
3577c478bdstevel@tonic-gate
3587c478bdstevel@tonic-gate/*****************************************************************************/
3597c478bdstevel@tonic-gate
360f928ce6ceasthastatic void
361f928ce6ceasthaarguments(void)
3627c478bdstevel@tonic-gate{
3637c478bdstevel@tonic-gate
3647c478bdstevel@tonic-gate/*
3657c478bdstevel@tonic-gate *
3667c478bdstevel@tonic-gate * Makes sure all the non-option command line arguments are processed. If we get
3677c478bdstevel@tonic-gate * here and there aren't any arguments left, or if '-' is one of the input files
3687c478bdstevel@tonic-gate * we'll translate stdin. Assumes input files are part of a single PostScript
3697c478bdstevel@tonic-gate * job and fonts can be downloaded at the start of each file.
3707c478bdstevel@tonic-gate *
3717c478bdstevel@tonic-gate */
3727c478bdstevel@tonic-gate
3737c478bdstevel@tonic-gate    if ( argc < 1 )
3747c478bdstevel@tonic-gate	download();
3757c478bdstevel@tonic-gate    else {
3767c478bdstevel@tonic-gate	while ( argc > 0 ) {
3777c478bdstevel@tonic-gate	    fp_temp = NULL;
3787c478bdstevel@tonic-gate	    if ( strcmp(*argv, "-") == 0 )
3797c478bdstevel@tonic-gate		fp_in = stdin;
3807c478bdstevel@tonic-gate	    else if ( (fp_in = fopen(*argv, "r")) == NULL )
3817c478bdstevel@tonic-gate		error(FATAL, "can't open %s", *argv);
3827c478bdstevel@tonic-gate	    download();
3837c478bdstevel@tonic-gate	    if ( fp_in != stdin )
3847c478bdstevel@tonic-gate		fclose(fp_in);
3857c478bdstevel@tonic-gate	    if ( fp_temp != NULL )
3867c478bdstevel@tonic-gate		fclose(fp_temp);
3877c478bdstevel@tonic-gate	    argc--;
3887c478bdstevel@tonic-gate	    argv++;
3897c478bdstevel@tonic-gate	}   /* End while */
3907c478bdstevel@tonic-gate    }	/* End else */
3917c478bdstevel@tonic-gate
3927c478bdstevel@tonic-gate}   /* End of arguments */
3937c478bdstevel@tonic-gate
3947c478bdstevel@tonic-gate/*****************************************************************************/
3957c478bdstevel@tonic-gate
396f928ce6ceasthastatic void
397f928ce6ceasthadone(void)
3987c478bdstevel@tonic-gate{
3997c478bdstevel@tonic-gate
4007c478bdstevel@tonic-gate/*
4017c478bdstevel@tonic-gate *
4027c478bdstevel@tonic-gate * Clean things up before we quit.
4037c478bdstevel@tonic-gate *
4047c478bdstevel@tonic-gate */
4057c478bdstevel@tonic-gate
4067c478bdstevel@tonic-gate    if ( temp_file != NULL )
4077c478bdstevel@tonic-gate	unlink(temp_file);
4087c478bdstevel@tonic-gate
4097c478bdstevel@tonic-gate}   /* End of done */
4107c478bdstevel@tonic-gate
4117c478bdstevel@tonic-gate/*****************************************************************************/
4127c478bdstevel@tonic-gate
413f928ce6ceasthastatic void
414f928ce6ceasthadownload(void)
4157c478bdstevel@tonic-gate{
4167c478bdstevel@tonic-gate    int		infontlist = FALSE;
4177c478bdstevel@tonic-gate
4187c478bdstevel@tonic-gate/*
4197c478bdstevel@tonic-gate *
4207c478bdstevel@tonic-gate * If next is zero the map table is empty and all we do is copy the input file
4217c478bdstevel@tonic-gate * to stdout. Otherwise we read the input file looking for %%DocumentFonts: or
4227c478bdstevel@tonic-gate * continuation comments, add any accessible fonts to the output file, and then
4237c478bdstevel@tonic-gate * append the input file. When reading stdin we append lines to fp_temp and
4247c478bdstevel@tonic-gate * recover them when we're ready to copy the input file. fp_temp will often
4257c478bdstevel@tonic-gate * only contain part of stdin - if there's no %%DocumentFonts: (atend) comment
4267c478bdstevel@tonic-gate * we stop reading fp_in after the header.
4277c478bdstevel@tonic-gate *
4287c478bdstevel@tonic-gate */
4297c478bdstevel@tonic-gate
4307c478bdstevel@tonic-gate    if ( next > 0 ) {
4317c478bdstevel@tonic-gate	if ( fp_in == stdin ) {
4327c478bdstevel@tonic-gate	    if ( (temp_file = tempnam(temp_dir, "post")) == NULL )
4337c478bdstevel@tonic-gate		error(FATAL, "can't generate temp file name");
4347c478bdstevel@tonic-gate	    if ( (fp_temp = fopen(temp_file, "w+")) == NULL )
4357c478bdstevel@tonic-gate		error(FATAL, "can't open %s", temp_file);
4367c478bdstevel@tonic-gate	    unlink(temp_file);
4377c478bdstevel@tonic-gate	    temp_file = NULL;
4387c478bdstevel@tonic-gate	}   /* End if */
4397c478bdstevel@tonic-gate
4407c478bdstevel@tonic-gate	while ( fgets(buf, sizeof(buf), fp_in) != NULL ) {
4417c478bdstevel@tonic-gate	    if ( fp_temp != NULL )
4427c478bdstevel@tonic-gate		fprintf(fp_temp, "%s", buf);
4437c478bdstevel@tonic-gate	    if ( buf[0] != '%' || buf[1] != '%' ) {
4447c478bdstevel@tonic-gate		if ( (buf[0] != '%' || buf[1] != '!') && atend == FALSE )
4457c478bdstevel@tonic-gate		    break;
4467c478bdstevel@tonic-gate		infontlist = FALSE;
4477c478bdstevel@tonic-gate	    } else if ( strncmp(buf, comment, strlen(comment)) == 0 ) {
4487c478bdstevel@tonic-gate		copyfonts(buf);
4497c478bdstevel@tonic-gate		infontlist = TRUE;
4507c478bdstevel@tonic-gate	    } else if ( buf[2] == '+' && infontlist == TRUE )
4517c478bdstevel@tonic-gate		copyfonts(buf);
4527c478bdstevel@tonic-gate	    else infontlist = FALSE;
4537c478bdstevel@tonic-gate	}   /* End while */
4547c478bdstevel@tonic-gate    }	/* End if */
4557c478bdstevel@tonic-gate
4567c478bdstevel@tonic-gate    copyinput();
4577c478bdstevel@tonic-gate
4587c478bdstevel@tonic-gate}   /* End of download */
4597c478bdstevel@tonic-gate
4607c478bdstevel@tonic-gate/*****************************************************************************/
4617c478bdstevel@tonic-gate
462f928ce6ceasthastatic void
463f928ce6ceasthacopyfonts(char *list)
4647c478bdstevel@tonic-gate{
4657c478bdstevel@tonic-gate    char	*font;
4667c478bdstevel@tonic-gate    char	*path;
4677c478bdstevel@tonic-gate    int		n;
4687c478bdstevel@tonic-gate
4697c478bdstevel@tonic-gate/*
4707c478bdstevel@tonic-gate *
4717c478bdstevel@tonic-gate * list points to a %%DocumentFonts: or continuation comment. What follows the
4727c478bdstevel@tonic-gate * the keyword will be a list of fonts separated by white space (or (atend)).
4737c478bdstevel@tonic-gate * Look for each font in the map table and if it's found copy the font file to
4747c478bdstevel@tonic-gate * stdout (once only).
4757c478bdstevel@tonic-gate *
4767c478bdstevel@tonic-gate */
4777c478bdstevel@tonic-gate
4787c478bdstevel@tonic-gate    strtok(list, " \n");		/* skip to the font list */
4797c478bdstevel@tonic-gate
4807c478bdstevel@tonic-gate    while ( (font = strtok(NULL, " \t\n")) != NULL ) {
4817c478bdstevel@tonic-gate	if ( strcmp(font, ATEND) == 0 ) {
4827c478bdstevel@tonic-gate	    atend = TRUE;
4837c478bdstevel@tonic-gate	    break;
4847c478bdstevel@tonic-gate	}   /* End if */
4857c478bdstevel@tonic-gate	if ( (n = lookup(font)) < next ) {
4867c478bdstevel@tonic-gate	    if ( *map[n].file != '/' ) {
4877c478bdstevel@tonic-gate		if ( (path = malloc(strlen(hostfontdir)+strlen(map[n].file)+2)) == NULL )
4887c478bdstevel@tonic-gate		    error(FATAL, "no memory");
4897c478bdstevel@tonic-gate		sprintf(path, "%s/%s", hostfontdir, map[n].file);
4907c478bdstevel@tonic-gate		cat(path);
4917c478bdstevel@tonic-gate		free(path);
4927c478bdstevel@tonic-gate	    } else cat(map[n].file);
4937c478bdstevel@tonic-gate	    map[n].downloaded = TRUE;
4947c478bdstevel@tonic-gate	}   /* End if */
4957c478bdstevel@tonic-gate    }	/* End while */
4967c478bdstevel@tonic-gate
4977c478bdstevel@tonic-gate}   /* End of copyfonts */
4987c478bdstevel@tonic-gate
4997c478bdstevel@tonic-gate/*****************************************************************************/
5007c478bdstevel@tonic-gate
501f928ce6ceasthastatic void
502f928ce6ceasthacopyinput(void)
5037c478bdstevel@tonic-gate{
5047c478bdstevel@tonic-gate
5057c478bdstevel@tonic-gate/*
5067c478bdstevel@tonic-gate *
5077c478bdstevel@tonic-gate * Copies the input file to stdout. If fp_temp isn't NULL seek to the start and
5087c478bdstevel@tonic-gate * add it to the output file - it's a partial (or complete) copy of stdin made
5097c478bdstevel@tonic-gate * by download(). Then copy fp_in, but only seek to the start if it's not stdin.
5107c478bdstevel@tonic-gate *
5117c478bdstevel@tonic-gate */
5127c478bdstevel@tonic-gate
5137c478bdstevel@tonic-gate    if ( fp_temp != NULL ) {
5147c478bdstevel@tonic-gate	fseek(fp_temp, 0L, 0);
5157c478bdstevel@tonic-gate	while ( fgets(buf, sizeof(buf), fp_temp) != NULL )
5167c478bdstevel@tonic-gate	    printf("%s", buf);
5177c478bdstevel@tonic-gate    }	/* End if */
5187c478bdstevel@tonic-gate
5197c478bdstevel@tonic-gate    if ( fp_in != stdin )
5207c478bdstevel@tonic-gate	fseek(fp_in, 0L, 0);
5217c478bdstevel@tonic-gate
5227c478bdstevel@tonic-gate    while ( fgets(buf, sizeof(buf), fp_in) != NULL )
5237c478bdstevel@tonic-gate	printf("%s", buf);
5247c478bdstevel@tonic-gate
5257c478bdstevel@tonic-gate}   /* End of copyinput */
5267c478bdstevel@tonic-gate
5277c478bdstevel@tonic-gate/*****************************************************************************/
5287c478bdstevel@tonic-gate
529f928ce6ceasthastatic int
530f928ce6ceasthalookup(char *font)
5317c478bdstevel@tonic-gate{
5327c478bdstevel@tonic-gate    int		i;
5337c478bdstevel@tonic-gate
5347c478bdstevel@tonic-gate/*
5357c478bdstevel@tonic-gate *
5367c478bdstevel@tonic-gate * Looks for *font in the map table. Return the map table index if found and
5377c478bdstevel@tonic-gate * not yet downloaded - otherwise return next.
5387c478bdstevel@tonic-gate *
5397c478bdstevel@tonic-gate */
5407c478bdstevel@tonic-gate
5417c478bdstevel@tonic-gate    for ( i = 0; i < next; i++ )
5427c478bdstevel@tonic-gate	if ( strcmp(font, map[i].font) == 0 ) {
5437c478bdstevel@tonic-gate	    if ( map[i].downloaded == TRUE )
5447c478bdstevel@tonic-gate		i = next;
5457c478bdstevel@tonic-gate	    break;
5467c478bdstevel@tonic-gate	}   /* End if */
5477c478bdstevel@tonic-gate
5487c478bdstevel@tonic-gate    return(i);
5497c478bdstevel@tonic-gate
5507c478bdstevel@tonic-gate}   /* End of lookup */
5517c478bdstevel@tonic-gate
5527c478bdstevel@tonic-gate/*****************************************************************************/
5537c478bdstevel@tonic-gate
554f928ce6ceasthastatic Map *
555f928ce6ceasthaallocate(Map *ptr, int num)
5567c478bdstevel@tonic-gate{
5577c478bdstevel@tonic-gate
5587c478bdstevel@tonic-gate/*
5597c478bdstevel@tonic-gate *
5607c478bdstevel@tonic-gate * Allocates space for num Map elements. Calls malloc() if ptr is NULL and
5617c478bdstevel@tonic-gate * realloc() otherwise.
5627c478bdstevel@tonic-gate *
5637c478bdstevel@tonic-gate */
5647c478bdstevel@tonic-gate
5657c478bdstevel@tonic-gate    if ( ptr == NULL )
5667c478bdstevel@tonic-gate	ptr = (Map *)malloc(num * sizeof(Map));
5677c478bdstevel@tonic-gate    else ptr = (Map *)realloc(ptr, num * sizeof(Map));
5687c478bdstevel@tonic-gate
5697c478bdstevel@tonic-gate    if ( ptr == NULL )
5707c478bdstevel@tonic-gate	error(FATAL, "no map memory");
5717c478bdstevel@tonic-gate
5727c478bdstevel@tonic-gate    return(ptr);
5737c478bdstevel@tonic-gate
5747c478bdstevel@tonic-gate}   /* End of allocate */
575