1*219b2ee8SDavid du Colombier /* 2*219b2ee8SDavid du Colombier * 3*219b2ee8SDavid du Colombier * download - host resident font downloader 4*219b2ee8SDavid du Colombier * 5*219b2ee8SDavid du Colombier * Prepends host resident fonts to PostScript input files. The program assumes 6*219b2ee8SDavid du Colombier * the input files are part of a single PostScript job and that requested fonts 7*219b2ee8SDavid du Colombier * can be downloaded at the start of each input file. Downloaded fonts are the 8*219b2ee8SDavid du Colombier * ones named in a %%DocumentFonts: comment and listed in a special map table. 9*219b2ee8SDavid du Colombier * Map table pathnames (supplied using the -m option) that begin with a / are 10*219b2ee8SDavid du Colombier * taken as is. Otherwise the final pathname is built using *hostfontdir (-H 11*219b2ee8SDavid du Colombier * option), *mapname (-m option), and *suffix. 12*219b2ee8SDavid du Colombier * 13*219b2ee8SDavid du Colombier * The map table consists of fontname-filename pairs, separated by white space. 14*219b2ee8SDavid du Colombier * Comments are introduced by % (as in PostScript) and extend to the end of the 15*219b2ee8SDavid du Colombier * current line. The only fonts that can be downloaded are the ones listed in 16*219b2ee8SDavid du Colombier * the active map table that point the program to a readable Unix file. A request 17*219b2ee8SDavid du Colombier * for an unlisted font or inaccessible file is ignored. All font requests are 18*219b2ee8SDavid du Colombier * ignored if the map table can't be read. In that case the program simply copies 19*219b2ee8SDavid du Colombier * the input files to stdout. 20*219b2ee8SDavid du Colombier * 21*219b2ee8SDavid du Colombier * An example (but not one to follow) of what can be in a map table is, 22*219b2ee8SDavid du Colombier * 23*219b2ee8SDavid du Colombier * % 24*219b2ee8SDavid du Colombier * % Map requests for Bookman-Light to file *hostfontdir/KR 25*219b2ee8SDavid du Colombier * % 26*219b2ee8SDavid du Colombier * 27*219b2ee8SDavid du Colombier * Bookman-Light KR % Keeping everything (including the map 28*219b2ee8SDavid du Colombier * % table) in *hostfontdir seems like the 29*219b2ee8SDavid du Colombier * % cleanest approach. 30*219b2ee8SDavid du Colombier * 31*219b2ee8SDavid du Colombier * % 32*219b2ee8SDavid du Colombier * % Map Palatino-Roman to file *hostfontdir/palatino/Roman 33*219b2ee8SDavid du Colombier * % 34*219b2ee8SDavid du Colombier * Palatino-Roman palatino/Roman 35*219b2ee8SDavid du Colombier * 36*219b2ee8SDavid du Colombier * % Map ZapfDingbats to file /usr/lib/host/dingbats 37*219b2ee8SDavid du Colombier * 38*219b2ee8SDavid du Colombier * ZapfDingbats /usr/lib/host/dingbats 39*219b2ee8SDavid du Colombier * 40*219b2ee8SDavid du Colombier * Once again, file names that begin with a / are taken as is. All others have 41*219b2ee8SDavid du Colombier * *hostfontdir/ prepended to the file string associated with a particular font. 42*219b2ee8SDavid du Colombier * 43*219b2ee8SDavid du Colombier * Map table can be associated with a printer model (e.g. a LaserWriter), a 44*219b2ee8SDavid du Colombier * printer destination, or whatever - the choice is up to an administrator. 45*219b2ee8SDavid du Colombier * By destination may be best if your spooler is running several private 46*219b2ee8SDavid du Colombier * printers. Host resident fonts are usually purchased under a license that 47*219b2ee8SDavid du Colombier * restricts their use to a limited number of printers. A font licensed for 48*219b2ee8SDavid du Colombier * a single printer should only be used on that printer. 49*219b2ee8SDavid du Colombier * 50*219b2ee8SDavid du Colombier * Was written quickly, so there's much room for improvement. Undoubtedly should 51*219b2ee8SDavid du Colombier * be a more general program (e.g. scan for other comments). 52*219b2ee8SDavid du Colombier * 53*219b2ee8SDavid du Colombier */ 54*219b2ee8SDavid du Colombier 55*219b2ee8SDavid du Colombier #include <stdio.h> 56*219b2ee8SDavid du Colombier #include <signal.h> 57*219b2ee8SDavid du Colombier #include <sys/types.h> 58*219b2ee8SDavid du Colombier #include <fcntl.h> 59*219b2ee8SDavid du Colombier #include <sys/stat.h> 60*219b2ee8SDavid du Colombier #include <string.h> 61*219b2ee8SDavid du Colombier 62*219b2ee8SDavid du Colombier #include "comments.h" /* PostScript file structuring comments */ 63*219b2ee8SDavid du Colombier #include "gen.h" /* general purpose definitions */ 64*219b2ee8SDavid du Colombier #include "path.h" /* for temporary directory */ 65*219b2ee8SDavid du Colombier #include "ext.h" /* external variable declarations */ 66*219b2ee8SDavid du Colombier #include "download.h" /* a few special definitions */ 67*219b2ee8SDavid du Colombier 68*219b2ee8SDavid du Colombier char *temp_dir = TEMPDIR; /* temp directory - for copying stdin */ 69*219b2ee8SDavid du Colombier char *hostfontdir = HOSTDIR; /* host resident directory */ 70*219b2ee8SDavid du Colombier char *mapname = "map"; /* map table - usually in *hostfontdir */ 71*219b2ee8SDavid du Colombier char *suffix = ""; /* appended to the map table pathname */ 72*219b2ee8SDavid du Colombier Map *map = NULL; /* device font map table */ 73*219b2ee8SDavid du Colombier char *stringspace = NULL; /* for storing font and file strings */ 74*219b2ee8SDavid du Colombier int next = 0; /* next free slot in map[] */ 75*219b2ee8SDavid du Colombier 76*219b2ee8SDavid du Colombier char *residentfonts = NULL; /* list of printer resident fonts */ 77*219b2ee8SDavid du Colombier char *printer = NULL; /* printer name - only for Unix 4.0 lp */ 78*219b2ee8SDavid du Colombier 79*219b2ee8SDavid du Colombier char buf[2048]; /* input file line buffer */ 80*219b2ee8SDavid du Colombier char *comment = DOCUMENTFONTS; /* look for this comment */ 81*219b2ee8SDavid du Colombier int atend = FALSE; /* TRUE only if a comment says so */ 82*219b2ee8SDavid du Colombier 83*219b2ee8SDavid du Colombier FILE *fp_in = stdin; /* next input file */ 84*219b2ee8SDavid du Colombier FILE *fp_temp = NULL; /* for copying stdin */ 85*219b2ee8SDavid du Colombier 86*219b2ee8SDavid du Colombier /*****************************************************************************/ 87*219b2ee8SDavid du Colombier 88*219b2ee8SDavid du Colombier main(agc, agv) 89*219b2ee8SDavid du Colombier 90*219b2ee8SDavid du Colombier int agc; 91*219b2ee8SDavid du Colombier char *agv[]; 92*219b2ee8SDavid du Colombier 93*219b2ee8SDavid du Colombier { 94*219b2ee8SDavid du Colombier 95*219b2ee8SDavid du Colombier /* 96*219b2ee8SDavid du Colombier * 97*219b2ee8SDavid du Colombier * Host resident font downloader. The input files are assumed to be part of a 98*219b2ee8SDavid du Colombier * single PostScript job. 99*219b2ee8SDavid du Colombier * 100*219b2ee8SDavid du Colombier */ 101*219b2ee8SDavid du Colombier 102*219b2ee8SDavid du Colombier argc = agc; /* other routines may want them */ 103*219b2ee8SDavid du Colombier argv = agv; 104*219b2ee8SDavid du Colombier 105*219b2ee8SDavid du Colombier prog_name = argv[0]; /* just for error messages */ 106*219b2ee8SDavid du Colombier 107*219b2ee8SDavid du Colombier init_signals(); /* sets up interrupt handling */ 108*219b2ee8SDavid du Colombier options(); /* first get command line options */ 109*219b2ee8SDavid du Colombier readmap(); /* read the font map table */ 110*219b2ee8SDavid du Colombier readresident(); /* and the optional resident font list */ 111*219b2ee8SDavid du Colombier arguments(); /* then process non-option arguments */ 112*219b2ee8SDavid du Colombier done(); /* and clean things up */ 113*219b2ee8SDavid du Colombier exit(x_stat); /* not much could be wrong */ 114*219b2ee8SDavid du Colombier 115*219b2ee8SDavid du Colombier } /* End of main */ 116*219b2ee8SDavid du Colombier 117*219b2ee8SDavid du Colombier /*****************************************************************************/ 118*219b2ee8SDavid du Colombier 119*219b2ee8SDavid du Colombier init_signals() 120*219b2ee8SDavid du Colombier 121*219b2ee8SDavid du Colombier { 122*219b2ee8SDavid du Colombier 123*219b2ee8SDavid du Colombier /* 124*219b2ee8SDavid du Colombier * 125*219b2ee8SDavid du Colombier * Makes sure we handle interrupts properly. 126*219b2ee8SDavid du Colombier * 127*219b2ee8SDavid du Colombier */ 128*219b2ee8SDavid du Colombier 129*219b2ee8SDavid du Colombier if ( signal(SIGINT, interrupt) == SIG_IGN ) { 130*219b2ee8SDavid du Colombier signal(SIGINT, SIG_IGN); 131*219b2ee8SDavid du Colombier signal(SIGQUIT, SIG_IGN); 132*219b2ee8SDavid du Colombier signal(SIGHUP, SIG_IGN); 133*219b2ee8SDavid du Colombier } else { 134*219b2ee8SDavid du Colombier signal(SIGHUP, interrupt); 135*219b2ee8SDavid du Colombier signal(SIGQUIT, interrupt); 136*219b2ee8SDavid du Colombier } /* End else */ 137*219b2ee8SDavid du Colombier 138*219b2ee8SDavid du Colombier signal(SIGTERM, interrupt); 139*219b2ee8SDavid du Colombier 140*219b2ee8SDavid du Colombier } /* End of init_signals */ 141*219b2ee8SDavid du Colombier 142*219b2ee8SDavid du Colombier /*****************************************************************************/ 143*219b2ee8SDavid du Colombier 144*219b2ee8SDavid du Colombier options() 145*219b2ee8SDavid du Colombier 146*219b2ee8SDavid du Colombier { 147*219b2ee8SDavid du Colombier 148*219b2ee8SDavid du Colombier int ch; /* return value from getopt() */ 149*219b2ee8SDavid du Colombier char *optnames = "c:fm:p:r:H:T:DI"; 150*219b2ee8SDavid du Colombier 151*219b2ee8SDavid du Colombier extern char *optarg; /* used by getopt() */ 152*219b2ee8SDavid du Colombier extern int optind; 153*219b2ee8SDavid du Colombier 154*219b2ee8SDavid du Colombier /* 155*219b2ee8SDavid du Colombier * 156*219b2ee8SDavid du Colombier * Reads and processes the command line options. 157*219b2ee8SDavid du Colombier * 158*219b2ee8SDavid du Colombier */ 159*219b2ee8SDavid du Colombier 160*219b2ee8SDavid du Colombier while ( (ch = getopt(argc, argv, optnames)) != EOF ) { 161*219b2ee8SDavid du Colombier switch ( ch ) { 162*219b2ee8SDavid du Colombier case 'c': /* look for this comment */ 163*219b2ee8SDavid du Colombier comment = optarg; 164*219b2ee8SDavid du Colombier break; 165*219b2ee8SDavid du Colombier 166*219b2ee8SDavid du Colombier case 'f': /* force a complete input file scan */ 167*219b2ee8SDavid du Colombier atend = TRUE; 168*219b2ee8SDavid du Colombier break; 169*219b2ee8SDavid du Colombier 170*219b2ee8SDavid du Colombier case 'm': /* printer map table name */ 171*219b2ee8SDavid du Colombier mapname = optarg; 172*219b2ee8SDavid du Colombier break; 173*219b2ee8SDavid du Colombier 174*219b2ee8SDavid du Colombier case 'p': /* printer name - for Unix 4.0 lp */ 175*219b2ee8SDavid du Colombier printer = optarg; 176*219b2ee8SDavid du Colombier break; 177*219b2ee8SDavid du Colombier 178*219b2ee8SDavid du Colombier case 'r': /* resident font list */ 179*219b2ee8SDavid du Colombier residentfonts = optarg; 180*219b2ee8SDavid du Colombier break; 181*219b2ee8SDavid du Colombier 182*219b2ee8SDavid du Colombier case 'H': /* host resident font directory */ 183*219b2ee8SDavid du Colombier hostfontdir = optarg; 184*219b2ee8SDavid du Colombier break; 185*219b2ee8SDavid du Colombier 186*219b2ee8SDavid du Colombier case 'T': /* temporary file directory */ 187*219b2ee8SDavid du Colombier temp_dir = optarg; 188*219b2ee8SDavid du Colombier break; 189*219b2ee8SDavid du Colombier 190*219b2ee8SDavid du Colombier case 'D': /* debug flag */ 191*219b2ee8SDavid du Colombier debug = ON; 192*219b2ee8SDavid du Colombier break; 193*219b2ee8SDavid du Colombier 194*219b2ee8SDavid du Colombier case 'I': /* ignore FATAL errors */ 195*219b2ee8SDavid du Colombier ignore = ON; 196*219b2ee8SDavid du Colombier break; 197*219b2ee8SDavid du Colombier 198*219b2ee8SDavid du Colombier case '?': /* don't understand the option */ 199*219b2ee8SDavid du Colombier error(FATAL, ""); 200*219b2ee8SDavid du Colombier break; 201*219b2ee8SDavid du Colombier 202*219b2ee8SDavid du Colombier default: /* don't know what to do for ch */ 203*219b2ee8SDavid du Colombier error(FATAL, "missing case for option %c\n", ch); 204*219b2ee8SDavid du Colombier break; 205*219b2ee8SDavid du Colombier } /* End switch */ 206*219b2ee8SDavid du Colombier } /* End while */ 207*219b2ee8SDavid du Colombier 208*219b2ee8SDavid du Colombier argc -= optind; /* get ready for non-option args */ 209*219b2ee8SDavid du Colombier argv += optind; 210*219b2ee8SDavid du Colombier 211*219b2ee8SDavid du Colombier } /* End of options */ 212*219b2ee8SDavid du Colombier 213*219b2ee8SDavid du Colombier /*****************************************************************************/ 214*219b2ee8SDavid du Colombier 215*219b2ee8SDavid du Colombier readmap() 216*219b2ee8SDavid du Colombier 217*219b2ee8SDavid du Colombier { 218*219b2ee8SDavid du Colombier 219*219b2ee8SDavid du Colombier char *path; 220*219b2ee8SDavid du Colombier char *ptr; 221*219b2ee8SDavid du Colombier int fd; 222*219b2ee8SDavid du Colombier struct stat sbuf; 223*219b2ee8SDavid du Colombier 224*219b2ee8SDavid du Colombier /* 225*219b2ee8SDavid du Colombier * 226*219b2ee8SDavid du Colombier * Initializes the map table by reading an ASCII mapping file. If mapname begins 227*219b2ee8SDavid du Colombier * with a / it's the map table. Otherwise hostfontdir, mapname, and suffix are 228*219b2ee8SDavid du Colombier * combined to build the final pathname. If we can open the file we read it all 229*219b2ee8SDavid du Colombier * into memory, erase comments, and separate the font and file name pairs. When 230*219b2ee8SDavid du Colombier * we leave next points to the next free slot in the map[] array. If it's zero 231*219b2ee8SDavid du Colombier * nothing was in the file or we couldn't open it. 232*219b2ee8SDavid du Colombier * 233*219b2ee8SDavid du Colombier */ 234*219b2ee8SDavid du Colombier 235*219b2ee8SDavid du Colombier if ( hostfontdir == NULL || mapname == NULL ) 236*219b2ee8SDavid du Colombier return; 237*219b2ee8SDavid du Colombier 238*219b2ee8SDavid du Colombier if ( *mapname != '/' ) { 239*219b2ee8SDavid du Colombier if ( (path = (char *)malloc(strlen(hostfontdir) + strlen(mapname) + 240*219b2ee8SDavid du Colombier strlen(suffix) + 2)) == NULL ) 241*219b2ee8SDavid du Colombier error(FATAL, "no memory"); 242*219b2ee8SDavid du Colombier sprintf(path, "%s/%s%s", hostfontdir, mapname, suffix); 243*219b2ee8SDavid du Colombier } else path = mapname; 244*219b2ee8SDavid du Colombier 245*219b2ee8SDavid du Colombier if ( (fd = open(path, 0)) != -1 ) { 246*219b2ee8SDavid du Colombier if ( fstat(fd, &sbuf) == -1 ) 247*219b2ee8SDavid du Colombier error(FATAL, "can't fstat %s", path); 248*219b2ee8SDavid du Colombier if ( (stringspace = (char *)malloc(sbuf.st_size + 2)) == NULL ) 249*219b2ee8SDavid du Colombier error(FATAL, "no memory"); 250*219b2ee8SDavid du Colombier if ( read(fd, stringspace, sbuf.st_size) == -1 ) 251*219b2ee8SDavid du Colombier error(FATAL, "can't read %s", path); 252*219b2ee8SDavid du Colombier close(fd); 253*219b2ee8SDavid du Colombier 254*219b2ee8SDavid du Colombier stringspace[sbuf.st_size] = '\n'; /* just to be safe */ 255*219b2ee8SDavid du Colombier stringspace[sbuf.st_size+1] = '\0'; 256*219b2ee8SDavid du Colombier for ( ptr = stringspace; *ptr != '\0'; ptr++ ) /* erase comments */ 257*219b2ee8SDavid du Colombier if ( *ptr == '%' ) 258*219b2ee8SDavid du Colombier for ( ; *ptr != '\n' ; ptr++ ) 259*219b2ee8SDavid du Colombier *ptr = ' '; 260*219b2ee8SDavid du Colombier 261*219b2ee8SDavid du Colombier for ( ptr = stringspace; ; next++ ) { 262*219b2ee8SDavid du Colombier if ( (next % 50) == 0 ) 263*219b2ee8SDavid du Colombier map = allocate(map, next+50); 264*219b2ee8SDavid du Colombier map[next].downloaded = FALSE; 265*219b2ee8SDavid du Colombier map[next].font = strtok(ptr, " \t\n"); 266*219b2ee8SDavid du Colombier map[next].file = strtok(ptr = NULL, " \t\n"); 267*219b2ee8SDavid du Colombier if ( map[next].font == NULL ) 268*219b2ee8SDavid du Colombier break; 269*219b2ee8SDavid du Colombier if ( map[next].file == NULL ) 270*219b2ee8SDavid du Colombier error(FATAL, "map table format error - check %s", path); 271*219b2ee8SDavid du Colombier } /* End for */ 272*219b2ee8SDavid du Colombier } /* End if */ 273*219b2ee8SDavid du Colombier 274*219b2ee8SDavid du Colombier } /* End of readmap */ 275*219b2ee8SDavid du Colombier 276*219b2ee8SDavid du Colombier /*****************************************************************************/ 277*219b2ee8SDavid du Colombier 278*219b2ee8SDavid du Colombier readresident() 279*219b2ee8SDavid du Colombier 280*219b2ee8SDavid du Colombier { 281*219b2ee8SDavid du Colombier 282*219b2ee8SDavid du Colombier FILE *fp; 283*219b2ee8SDavid du Colombier char *path; 284*219b2ee8SDavid du Colombier int ch; 285*219b2ee8SDavid du Colombier int n; 286*219b2ee8SDavid du Colombier 287*219b2ee8SDavid du Colombier /* 288*219b2ee8SDavid du Colombier * 289*219b2ee8SDavid du Colombier * Reads a file that lists the resident fonts for a particular printer and marks 290*219b2ee8SDavid du Colombier * each font as already downloaded. Nothing's done if the file can't be read or 291*219b2ee8SDavid du Colombier * there's no mapping file. Comments, as in the map file, begin with a % and 292*219b2ee8SDavid du Colombier * extend to the end of the line. Added for Unix 4.0 lp. 293*219b2ee8SDavid du Colombier * 294*219b2ee8SDavid du Colombier */ 295*219b2ee8SDavid du Colombier 296*219b2ee8SDavid du Colombier if ( next == 0 || (printer == NULL && residentfonts == NULL) ) 297*219b2ee8SDavid du Colombier return; 298*219b2ee8SDavid du Colombier 299*219b2ee8SDavid du Colombier if ( printer != NULL ) { /* use Unix 4.0 lp pathnames */ 300*219b2ee8SDavid du Colombier sprintf(buf, "/etc/lp/printers/%s/residentfonts", printer); 301*219b2ee8SDavid du Colombier path = buf; 302*219b2ee8SDavid du Colombier } else path = residentfonts; 303*219b2ee8SDavid du Colombier 304*219b2ee8SDavid du Colombier if ( (fp = fopen(path, "r")) != NULL ) { 305*219b2ee8SDavid du Colombier while ( fscanf(fp, "%s", buf) != EOF ) 306*219b2ee8SDavid du Colombier if ( buf[0] == '%' ) 307*219b2ee8SDavid du Colombier while ( (ch = getc(fp)) != EOF && ch != '\n' ) ; 308*219b2ee8SDavid du Colombier else if ( (n = lookup(buf)) < next ) 309*219b2ee8SDavid du Colombier map[n].downloaded = TRUE; 310*219b2ee8SDavid du Colombier fclose(fp); 311*219b2ee8SDavid du Colombier } /* End if */ 312*219b2ee8SDavid du Colombier 313*219b2ee8SDavid du Colombier } /* End of readresident */ 314*219b2ee8SDavid du Colombier 315*219b2ee8SDavid du Colombier /*****************************************************************************/ 316*219b2ee8SDavid du Colombier 317*219b2ee8SDavid du Colombier arguments() 318*219b2ee8SDavid du Colombier 319*219b2ee8SDavid du Colombier { 320*219b2ee8SDavid du Colombier 321*219b2ee8SDavid du Colombier /* 322*219b2ee8SDavid du Colombier * 323*219b2ee8SDavid du Colombier * Makes sure all the non-option command line arguments are processed. If we get 324*219b2ee8SDavid du Colombier * here and there aren't any arguments left, or if '-' is one of the input files 325*219b2ee8SDavid du Colombier * we'll translate stdin. Assumes input files are part of a single PostScript 326*219b2ee8SDavid du Colombier * job and fonts can be downloaded at the start of each file. 327*219b2ee8SDavid du Colombier * 328*219b2ee8SDavid du Colombier */ 329*219b2ee8SDavid du Colombier 330*219b2ee8SDavid du Colombier if ( argc < 1 ) 331*219b2ee8SDavid du Colombier download(); 332*219b2ee8SDavid du Colombier else { 333*219b2ee8SDavid du Colombier while ( argc > 0 ) { 334*219b2ee8SDavid du Colombier fp_temp = NULL; 335*219b2ee8SDavid du Colombier if ( strcmp(*argv, "-") == 0 ) 336*219b2ee8SDavid du Colombier fp_in = stdin; 337*219b2ee8SDavid du Colombier else if ( (fp_in = fopen(*argv, "r")) == NULL ) 338*219b2ee8SDavid du Colombier error(FATAL, "can't open %s", *argv); 339*219b2ee8SDavid du Colombier download(); 340*219b2ee8SDavid du Colombier if ( fp_in != stdin ) 341*219b2ee8SDavid du Colombier fclose(fp_in); 342*219b2ee8SDavid du Colombier if ( fp_temp != NULL ) 343*219b2ee8SDavid du Colombier fclose(fp_temp); 344*219b2ee8SDavid du Colombier argc--; 345*219b2ee8SDavid du Colombier argv++; 346*219b2ee8SDavid du Colombier } /* End while */ 347*219b2ee8SDavid du Colombier } /* End else */ 348*219b2ee8SDavid du Colombier 349*219b2ee8SDavid du Colombier } /* End of arguments */ 350*219b2ee8SDavid du Colombier 351*219b2ee8SDavid du Colombier /*****************************************************************************/ 352*219b2ee8SDavid du Colombier 353*219b2ee8SDavid du Colombier done() 354*219b2ee8SDavid du Colombier 355*219b2ee8SDavid du Colombier { 356*219b2ee8SDavid du Colombier 357*219b2ee8SDavid du Colombier /* 358*219b2ee8SDavid du Colombier * 359*219b2ee8SDavid du Colombier * Clean things up before we quit. 360*219b2ee8SDavid du Colombier * 361*219b2ee8SDavid du Colombier */ 362*219b2ee8SDavid du Colombier 363*219b2ee8SDavid du Colombier if ( temp_file != NULL ) 364*219b2ee8SDavid du Colombier unlink(temp_file); 365*219b2ee8SDavid du Colombier 366*219b2ee8SDavid du Colombier } /* End of done */ 367*219b2ee8SDavid du Colombier 368*219b2ee8SDavid du Colombier /*****************************************************************************/ 369*219b2ee8SDavid du Colombier 370*219b2ee8SDavid du Colombier download() 371*219b2ee8SDavid du Colombier 372*219b2ee8SDavid du Colombier { 373*219b2ee8SDavid du Colombier 374*219b2ee8SDavid du Colombier int infontlist = FALSE; 375*219b2ee8SDavid du Colombier 376*219b2ee8SDavid du Colombier /* 377*219b2ee8SDavid du Colombier * 378*219b2ee8SDavid du Colombier * If next is zero the map table is empty and all we do is copy the input file 379*219b2ee8SDavid du Colombier * to stdout. Otherwise we read the input file looking for %%DocumentFonts: or 380*219b2ee8SDavid du Colombier * continuation comments, add any accessible fonts to the output file, and then 381*219b2ee8SDavid du Colombier * append the input file. When reading stdin we append lines to fp_temp and 382*219b2ee8SDavid du Colombier * recover them when we're ready to copy the input file. fp_temp will often 383*219b2ee8SDavid du Colombier * only contain part of stdin - if there's no %%DocumentFonts: (atend) comment 384*219b2ee8SDavid du Colombier * we stop reading fp_in after the header. 385*219b2ee8SDavid du Colombier * 386*219b2ee8SDavid du Colombier */ 387*219b2ee8SDavid du Colombier 388*219b2ee8SDavid du Colombier if ( next > 0 ) { 389*219b2ee8SDavid du Colombier if ( fp_in == stdin ) { 390*219b2ee8SDavid du Colombier if ( (temp_file = tempnam(temp_dir, "post")) == NULL ) 391*219b2ee8SDavid du Colombier error(FATAL, "can't generate temp file name"); 392*219b2ee8SDavid du Colombier if ( (fp_temp = fopen(temp_file, "w+r")) == NULL ) 393*219b2ee8SDavid du Colombier error(FATAL, "can't open %s", temp_file); 394*219b2ee8SDavid du Colombier unlink(temp_file); 395*219b2ee8SDavid du Colombier } /* End if */ 396*219b2ee8SDavid du Colombier 397*219b2ee8SDavid du Colombier while ( fgets(buf, sizeof(buf), fp_in) != NULL ) { 398*219b2ee8SDavid du Colombier if ( fp_temp != NULL ) 399*219b2ee8SDavid du Colombier fprintf(fp_temp, "%s", buf); 400*219b2ee8SDavid du Colombier if ( buf[0] != '%' || buf[1] != '%' ) { 401*219b2ee8SDavid du Colombier if ( (buf[0] != '%' || buf[1] != '!') && atend == FALSE ) 402*219b2ee8SDavid du Colombier break; 403*219b2ee8SDavid du Colombier infontlist = FALSE; 404*219b2ee8SDavid du Colombier } else if ( strncmp(buf, comment, strlen(comment)) == 0 ) { 405*219b2ee8SDavid du Colombier copyfonts(buf); 406*219b2ee8SDavid du Colombier infontlist = TRUE; 407*219b2ee8SDavid du Colombier } else if ( buf[2] == '+' && infontlist == TRUE ) 408*219b2ee8SDavid du Colombier copyfonts(buf); 409*219b2ee8SDavid du Colombier else infontlist = FALSE; 410*219b2ee8SDavid du Colombier } /* End while */ 411*219b2ee8SDavid du Colombier } /* End if */ 412*219b2ee8SDavid du Colombier 413*219b2ee8SDavid du Colombier copyinput(); 414*219b2ee8SDavid du Colombier 415*219b2ee8SDavid du Colombier } /* End of download */ 416*219b2ee8SDavid du Colombier 417*219b2ee8SDavid du Colombier /*****************************************************************************/ 418*219b2ee8SDavid du Colombier 419*219b2ee8SDavid du Colombier copyfonts(list) 420*219b2ee8SDavid du Colombier 421*219b2ee8SDavid du Colombier char *list; 422*219b2ee8SDavid du Colombier 423*219b2ee8SDavid du Colombier { 424*219b2ee8SDavid du Colombier 425*219b2ee8SDavid du Colombier char *font; 426*219b2ee8SDavid du Colombier char *path; 427*219b2ee8SDavid du Colombier int n; 428*219b2ee8SDavid du Colombier 429*219b2ee8SDavid du Colombier /* 430*219b2ee8SDavid du Colombier * 431*219b2ee8SDavid du Colombier * list points to a %%DocumentFonts: or continuation comment. What follows the 432*219b2ee8SDavid du Colombier * the keyword will be a list of fonts separated by white space (or (atend)). 433*219b2ee8SDavid du Colombier * Look for each font in the map table and if it's found copy the font file to 434*219b2ee8SDavid du Colombier * stdout (once only). 435*219b2ee8SDavid du Colombier * 436*219b2ee8SDavid du Colombier */ 437*219b2ee8SDavid du Colombier 438*219b2ee8SDavid du Colombier strtok(list, " \n"); /* skip to the font list */ 439*219b2ee8SDavid du Colombier 440*219b2ee8SDavid du Colombier while ( (font = strtok(NULL, " \t\n")) != NULL ) { 441*219b2ee8SDavid du Colombier if ( strcmp(font, ATEND) == 0 ) { 442*219b2ee8SDavid du Colombier atend = TRUE; 443*219b2ee8SDavid du Colombier break; 444*219b2ee8SDavid du Colombier } /* End if */ 445*219b2ee8SDavid du Colombier if ( (n = lookup(font)) < next ) { 446*219b2ee8SDavid du Colombier if ( *map[n].file != '/' ) { 447*219b2ee8SDavid du Colombier if ( (path = (char *)malloc(strlen(hostfontdir)+strlen(map[n].file)+2)) == NULL ) 448*219b2ee8SDavid du Colombier error(FATAL, "no memory"); 449*219b2ee8SDavid du Colombier sprintf(path, "%s/%s", hostfontdir, map[n].file); 450*219b2ee8SDavid du Colombier cat(path); 451*219b2ee8SDavid du Colombier free(path); 452*219b2ee8SDavid du Colombier } else cat(map[n].file); 453*219b2ee8SDavid du Colombier map[n].downloaded = TRUE; 454*219b2ee8SDavid du Colombier } /* End if */ 455*219b2ee8SDavid du Colombier } /* End while */ 456*219b2ee8SDavid du Colombier 457*219b2ee8SDavid du Colombier } /* End of copyfonts */ 458*219b2ee8SDavid du Colombier 459*219b2ee8SDavid du Colombier /*****************************************************************************/ 460*219b2ee8SDavid du Colombier 461*219b2ee8SDavid du Colombier copyinput() 462*219b2ee8SDavid du Colombier 463*219b2ee8SDavid du Colombier { 464*219b2ee8SDavid du Colombier 465*219b2ee8SDavid du Colombier /* 466*219b2ee8SDavid du Colombier * 467*219b2ee8SDavid du Colombier * Copies the input file to stdout. If fp_temp isn't NULL seek to the start and 468*219b2ee8SDavid du Colombier * add it to the output file - it's a partial (or complete) copy of stdin made 469*219b2ee8SDavid du Colombier * by download(). Then copy fp_in, but only seek to the start if it's not stdin. 470*219b2ee8SDavid du Colombier * 471*219b2ee8SDavid du Colombier */ 472*219b2ee8SDavid du Colombier 473*219b2ee8SDavid du Colombier if ( fp_temp != NULL ) { 474*219b2ee8SDavid du Colombier fseek(fp_temp, 0L, 0); 475*219b2ee8SDavid du Colombier while ( fgets(buf, sizeof(buf), fp_temp) != NULL ) 476*219b2ee8SDavid du Colombier printf("%s", buf); 477*219b2ee8SDavid du Colombier } /* End if */ 478*219b2ee8SDavid du Colombier 479*219b2ee8SDavid du Colombier if ( fp_in != stdin ) 480*219b2ee8SDavid du Colombier fseek(fp_in, 0L, 0); 481*219b2ee8SDavid du Colombier 482*219b2ee8SDavid du Colombier while ( fgets(buf, sizeof(buf), fp_in) != NULL ) 483*219b2ee8SDavid du Colombier printf("%s", buf); 484*219b2ee8SDavid du Colombier 485*219b2ee8SDavid du Colombier } /* End of copyinput */ 486*219b2ee8SDavid du Colombier 487*219b2ee8SDavid du Colombier /*****************************************************************************/ 488*219b2ee8SDavid du Colombier 489*219b2ee8SDavid du Colombier lookup(font) 490*219b2ee8SDavid du Colombier 491*219b2ee8SDavid du Colombier char *font; 492*219b2ee8SDavid du Colombier 493*219b2ee8SDavid du Colombier { 494*219b2ee8SDavid du Colombier 495*219b2ee8SDavid du Colombier int i; 496*219b2ee8SDavid du Colombier 497*219b2ee8SDavid du Colombier /* 498*219b2ee8SDavid du Colombier * 499*219b2ee8SDavid du Colombier * Looks for *font in the map table. Return the map table index if found and 500*219b2ee8SDavid du Colombier * not yet downloaded - otherwise return next. 501*219b2ee8SDavid du Colombier * 502*219b2ee8SDavid du Colombier */ 503*219b2ee8SDavid du Colombier 504*219b2ee8SDavid du Colombier for ( i = 0; i < next; i++ ) 505*219b2ee8SDavid du Colombier if ( strcmp(font, map[i].font) == 0 ) { 506*219b2ee8SDavid du Colombier if ( map[i].downloaded == TRUE ) 507*219b2ee8SDavid du Colombier i = next; 508*219b2ee8SDavid du Colombier break; 509*219b2ee8SDavid du Colombier } /* End if */ 510*219b2ee8SDavid du Colombier 511*219b2ee8SDavid du Colombier return(i); 512*219b2ee8SDavid du Colombier 513*219b2ee8SDavid du Colombier } /* End of lookup */ 514*219b2ee8SDavid du Colombier 515*219b2ee8SDavid du Colombier /*****************************************************************************/ 516*219b2ee8SDavid du Colombier 517*219b2ee8SDavid du Colombier Map *allocate(ptr, num) 518*219b2ee8SDavid du Colombier 519*219b2ee8SDavid du Colombier Map *ptr; 520*219b2ee8SDavid du Colombier int num; 521*219b2ee8SDavid du Colombier 522*219b2ee8SDavid du Colombier { 523*219b2ee8SDavid du Colombier 524*219b2ee8SDavid du Colombier /* 525*219b2ee8SDavid du Colombier * 526*219b2ee8SDavid du Colombier * Allocates space for num Map elements. Calls malloc() if ptr is NULL and 527*219b2ee8SDavid du Colombier * realloc() otherwise. 528*219b2ee8SDavid du Colombier * 529*219b2ee8SDavid du Colombier */ 530*219b2ee8SDavid du Colombier 531*219b2ee8SDavid du Colombier if ( ptr == NULL ) 532*219b2ee8SDavid du Colombier ptr = (Map *)malloc(num * sizeof(Map)); 533*219b2ee8SDavid du Colombier else ptr = (Map *)realloc(ptr, num * sizeof(Map)); 534*219b2ee8SDavid du Colombier 535*219b2ee8SDavid du Colombier if ( ptr == NULL ) 536*219b2ee8SDavid du Colombier error(FATAL, "no map memory"); 537*219b2ee8SDavid du Colombier 538*219b2ee8SDavid du Colombier return(ptr); 539*219b2ee8SDavid du Colombier 540*219b2ee8SDavid du Colombier } /* End of allocate */ 541*219b2ee8SDavid du Colombier 542*219b2ee8SDavid du Colombier /*****************************************************************************/ 543*219b2ee8SDavid du Colombier 544