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