/* * FILE: mtpk.c * * PURPOSE: generation of PK fonts from METAFONT or PostScript font * sources (see mtpk(1) for a functional description of mtpk * and mtpk(5) for the syntax of the configuration file * of mtpk). * * SYNOPSIS: * mtpk [-v] [-d] name dpi bdpi [ mode] * * AUTHOR: Piet Tutelaers * VERSION: 1.0 (November 1995) */ #define _POSIX_SOURCE 1 #include /* isalnum() */ #include /* errno */ #include #include /* opendir(), readdir(), closedir() */ #include /* open(), read(), write(), close() */ #ifdef UNIX #include /* getpwnam() */ #endif #include /* signal() */ #include /* getcwd() and a lot more ... */ #include /* atoi(), exit(), getenv(), malloc() */ #include /* strchr(), strcmp(), strcpy(), strerror(), strlen(), strncmp(), strncpy(), strrchr(), strstr() */ #include /* stat(), mkdir(), umask() */ #include /* time(), ctime() */ #include /* chdir(), getpid(), rmdir(), system(), unlink() */ /* UNIX: getuid(), seteuid() */ #include "basics.h" /* (*pfopen)(), my_fopen(), (*pstat)(), my_stat(), fatal(), msg() */ #include "filenames.h" /* newname() */ #include "psearch.h" /* init_pksearch(), path(), search_file(), search_pkfile(), search_flipath() */ #include "texfiles.h" /* sone(), four() */ #include "psinfo.h" /* psfont(), ps2pk_args() */ #include "cfg.h" /* read_cfg(), cfg_value() */ #include "PSres.h" /* ListPSResourceFiles() */ #ifdef NOSTRERROR char *sys_errlist; #define strerror(x) sys_errlist[x] #endif #ifdef MSDOS #define THROWAWAY "> NUL" #include "system.h" /* emx_system() */ #endif #ifndef THROWAWAY #define THROWAWAY ">/dev/null" #endif /* default order of renderers */ char *RENDORS = "mf+ps2pk+gsftopk"; int verbose = 0, debug = 0; /* We don't use any defaults in the program itself. * They are provided in mtpk.cfg */ char *flipath; char *mode = NULL; char *pkpath; char *tfmpath; char *tolerance; char *res; int oldfonts = 0; int bdpi = 0; int margin; int dpi, pkdest_dirtype, rm_forgedir = 0; char *texfont, *mag, *fliname, *tfmfile, *psname = NULL, *mapinfo = NULL; char currentdir[MAXSTRLEN], forgedir[MAXSTRLEN]; int real_uid = -1, eff_uid = -1; char *pkuser; /* prototypes of the functions we use */ void cleanup(char *dirname); int gsfont(char *fontmap, char *texfont); void installfont(char *pkfile); char *magnification (int dpi, int BDPI); void makefont(int cnt, char cmd[2][80], char target[2][80]); int matching(char *font, int size); main(int argc, char *argv[]) { char *pkname, *p, *rendors, *plus; int count, done, c; /* gather options */ while (--argc > 0 && (*++argv)[0] == '-') { done=0; while ((!done) && (c = (*++argv[0]))) switch (c) { case 'd': debug = 1; pstat = my_stat; break; case 'v': verbose = 1; pfopen = my_fopen; /* show PS resource databases found */ break; default: fatal("mtpk: %c illegal option\n", c); } } if (argc < 3) fatal("Usage: mtpk [-d] [-v] name dpi bdpi [mode]\n"); texfont = argv[0]; dpi = atoi(argv[1]); res = argv[2]; /* ignore fourth argument when magnification */ if (argc > 3) if (strchr(argv[3], '(') || strchr(argv[3], '+')) { if (verbose) msg("argument %s ignored\n", argv[3]); if (argc <= 5) mode = argv[4]; else fatal("Usage: mtpk [-d] [-v] name dpi bdpi [mode]\n"); } else if (argc == 4) mode = argv[3]; else fatal("Usage: mtpk [-d] [-v] name dpi bdpi [mode]\n"); /* read configuration parameters for res and mode */ if (read_cfg(res, mode)) if (res == NULL && mode == NULL) fatal("No default printer data available in mtpk.cfg\n"); else if (mode == NULL) fatal("No data available for %s dpi in mtpk.cfg\n", res); else fatal("No data available for %s dpi and %s in mtpk.cfg\n", res, mode); /* check if the PK font is really missing */ bdpi = atoi(res); mode = cfg_value("mode"); if ((pkpath = cfg_value("pkpath")) == NULL) fatal("definition of pkpath missing in mtpk.cfg\n"); if ((p = cfg_value("margin")) == NULL) margin = 0; else margin = atoi(p); tolerance = cfg_value("tolerance"); /* set global PK search parameters */ init_pksearch(bdpi, mode, margin, tolerance); /* round dpi to nearest half */ if (tolerance) { int trydpi; trydpi = nearesthalf(dpi); if (debug && trydpi != dpi) msg("%d rounded to %d (tolerance = %d)\n", dpi, trydpi, evaluate(tolerance, dpi)); dpi = trydpi; } flipath = cfg_value("flipath"); if (flipath != NULL && (fliname = search_flipath(flipath, matching))) fatal("%s: %s at %d dpi already available\n", fliname, texfont, dpi); pkname = search_pkfile(pkpath, texfont, dpi); if (pkname != NULL) fatal("%s: font already available\n", pkname); /* check if we have TFMpath before we are going to make font */ if ((tfmpath = cfg_value("tfmpath")) == NULL) fatal("definition of tfmpath missing in mtpk.cfg\n"); if (debug) msg("tfmpath = %s\n", tfmpath); /* check for `oldfonts' */ { char *old_fonts; old_fonts = cfg_value("oldfonts"); if (old_fonts != NULL && strcmp(old_fonts, "1") == 0) { oldfonts = 1; if (debug) msg("old style checksums will be used\n"); } } /* remember current directory */ if (getcwd(currentdir, MAXSTRLEN) == NULL) fatal("Could not determine current dir (%s)\n", strerror(errno)); /* When a directory in the PK path has write permission by * `pkuser' it will be considered as PUBLIC if this program has * set-UID execution permission. The value of `pkuser' can be * defined in mtpk.cfg. */ #ifdef UNIX real_uid = getuid(); if ((pkuser = cfg_value("pkuser")) != NULL) { struct passwd *pwe; if ((pwe = getpwnam(pkuser)) == NULL) msg("mtpk.cfg: pkuser = %s (undefined login)\n", pkuser); else { eff_uid = pwe->pw_uid; if (seteuid(eff_uid) == -1) { eff_uid = -1; if (debug) msg("mtpk: can not get x-permission for %s\n", pkuser); } else { if (debug) msg("mtpk: x-permission for %s\n", pkuser); seteuid(real_uid); } } } #endif rendors = cfg_value("rendors"); if (rendors == NULL) rendors = RENDORS; /* Is texfont a PostScript font? */ psname = psfont(texfont, &mapinfo); while (*rendors != '\0') { char renderer[32]; void try_mf(char *), try_ps2pk(), try_gsftopk(); count = 0; for (p = rendors; *p != '+' && *p != '\0'; p++) count++; strncpy(renderer, rendors, count); renderer[count] = '\0'; if (psname == NULL && strncmp(rendors, "mf", 2) == 0) { try_mf(renderer); fatal("%s: No font for %s\n", renderer, texfont); } else if (psname && strncmp(rendors, "ps2pk", 5) == 0) { if (debug) msg("ps2pk: using %s (%s)\n", psname, mapinfo); try_ps2pk(); if (verbose) msg("ps2pk: no font for %s\n", psname); } else if (psname && strncmp(rendors, "gsftopk", 7) == 0) { if (debug) msg("gsftopk: using %s (%s)\n", psname, mapinfo); try_gsftopk(); if (verbose) msg("gsftopk: no font for %s\n", psname); } rendors+= count; if (*rendors == '+') rendors++; } fatal("No font source for %s\n", texfont); } void try_mf(char *progname) { char *mfipath, *mfname; /* get mfipath (where the METAFONT sources are) */ if ((mfipath = cfg_value("mfipath")) == NULL) fatal("definition of mfipath missing in mtpk.cfg\n"); /* Do we have a METAFONT source for texfont ? */ mfname = search_file(mfipath, newname(texfont, ".mf"), FATAL); if (mfname != NULL) { char cmds[2][80], *dot; char targets[2][80]; sprintf(targets[0], "%s.%dgf", texfont, dpi); #ifdef MSDOS /* truncate */ dot = strchr(targets[0], '.'); *(dot+4) = '\0'; #endif #ifdef MSDOS sprintf(targets[1], "%s.pk", texfont, dpi); #else sprintf(targets[1], "%s.%dpk", texfont, dpi); #endif sprintf(cmds[0], "%s \"\\mode:=%s; mag:=%s; scrollmode; input %s\" %s", progname, mode, magnification(dpi, bdpi), texfont, debug ? "" : THROWAWAY); sprintf(cmds[1], "gftopk %s %s %s", targets[0], targets[1], debug ? "" : THROWAWAY); makefont(2, cmds, targets); if (strcmp(currentdir, forgedir) != 0) installfont(targets[1]); exit(0); } } void try_ps2pk() { char *psrespath, **names, **files, args[80]; int count; /* Get ps2pk arguments from mapinfo */ ps2pk_args(mapinfo, args); /* get psrespath for PostScript resources */ if ((psrespath = cfg_value("psrespath")) == NULL) fatal("psrespath undefined in mtpk.cfg\n"); if (debug) msg("psrespath = %s\n", psrespath); /* Do we have an outline font? */ count = ListPSResourceFiles(psrespath, NULL, "FontOutline", psname, &names, &files); if (verbose && count > 1) { int i; msg("More than one outline resource for %s\n", psname); for (i = 0; i < count; i++) msg("\t<%s>\n", files[i]); } if (count >= 1) { char cmds[1][80]; char targets[1][80]; char *yres; sprintf(targets[0], "%s.%dpk", texfont, dpi); if ((yres = cfg_value("yres")) != NULL) sprintf(cmds[0], "ps2pk %s%s-X%d -Y%s %s%s %s %s", debug ? "-v " : "", oldfonts ? "-O " : "", dpi, yres, args, psname, targets[0], debug ? "" : THROWAWAY); else sprintf(cmds[0], "ps2pk %s%s-X%d %s%s %s %s", debug ? "-v " : "", oldfonts ? "-O " : "", dpi, args, psname, targets[0], debug ? "" : THROWAWAY); makefont(1, cmds, targets); if (strcmp(currentdir, forgedir) != 0) installfont(targets[0]); exit(0); } } void try_gsftopk() { char *gsfontmap; if ((gsfontmap = cfg_value("gsfontmap")) == NULL) fatal("gsfontmap undefined in mtpk.cfg\n"); if (gsfont(gsfontmap, psname)) { char cmds[1][80]; char targets[1][80]; sprintf(targets[0], "%s.%dpk", texfont, dpi); sprintf(cmds[0], "gsftopk %s%s %d %s", debug ? "" : "-q ", texfont, dpi, debug ? "" : THROWAWAY); makefont(1, cmds, targets); if (strcmp(currentdir, forgedir) != 0) installfont(targets[0]); exit(0); } } /* * Compute METAFONT magnification string for */ int INT(float x) { return (int) x; } char mag_str[64]; char *magnification (int dpi, int BDPI) { double size, magstep; if (dpi == BDPI) { sprintf(mag_str, "magstep\\(0\\)"); return mag_str; } size = BDPI; magstep = 0; while (dpi < size) { size = size / 1.095445115; magstep -= 0.5; if (dpi == INT(size + 0.5)) { sprintf(mag_str, "magstep\\(%.1f\\)", magstep); return mag_str; } if (dpi > size) { sprintf(mag_str, "%d+%d/%d", INT(dpi/BDPI), dpi%BDPI, BDPI); return mag_str; } } while (dpi > size) { size = size * 1.095445115; magstep += 0.5; if (dpi == INT(size + 0.5)) { sprintf(mag_str, "magstep\\(%.1f\\)", magstep); return mag_str; } if (dpi < size) { sprintf(mag_str, "%d+%d/%d", INT(dpi/BDPI), dpi%BDPI, BDPI); return mag_str; } } } /* * Makefont() creates a PK font from the commands in . When one * of the targets in fails the program is stopped with a message. */ void makefont(int cnt, char cmd[2][80], char target[2][80]) { int i, rc; struct stat status; char *forge; unsigned int unique(); /* check if we have a TFM font before we leave the current dir */ tfmfile = search_file(tfmpath, newname(texfont, ".tfm"), NONFATAL); /* make an unique font forge directory */ if (forge = cfg_value("forge")) { i = 0; while (*forge != '\0') { if (*forge == '%' && *(forge+1) == 'u') { sprintf(&forgedir[i], "%d", unique()); forge+=2; i+=strlen(&forgedir[i]); continue; } forgedir[i++] = *forge++; } forgedir[i] = '\0'; /* make the directory? */ if (pstat(forgedir, &status) != 0) { if (mkdir(forgedir, 0755) == -1) fatal("%s: could not create (%s)\n", forgedir, strerror(errno)); if (debug) msg("%s: created forge directory\n", forgedir); rm_forgedir = 1; } if (chdir(forgedir) == -1) fatal("%s: could not chdir (%s)\n", forgedir, strerror(errno)); } else strcpy(forgedir, currentdir); for (i = 0; i < cnt; i++ ) { msg("%s\n", cmd[i]); #ifdef MSDOS rc = emx_system(cmd[i]); #else rc = system(cmd[i]); #endif if (rc == -1) fatal("%s\n", strerror(errno)); if (pstat(target[i], &status) != 0) { fatal("%s: failed\n", target[i]); } } if (verbose) msg("%s%c%s: created\n", forgedir, DIRSEP, target[cnt-1]); } enum type {UNKNOWN, PUBLIC_RO, PUBLIC_RW, PRIVATE, LASTRESORT}; #define public(m) ((m & 0170007) == 0040007) /* public directory */ #define private(m) ((m & 0170700) == 0040700) /* private directory */ #define readable(m) ((m & 0170007) == 0040705) /* read-only directory */ /* * Determine the type of the directory in which is * contained. If the file can not be accessed UNKNOWN is returned. * Otherwise the directory from which the file could be accessed is * returned in and its type is returned. The type LASTRESORT * will be returned if the file is accessable from the current * directory and PRIVATE when the directory is owned by the user. If * the directory is not owned by the user and not the current directory * PUBLIC_RO or PUBLIC_RW will be returned depending upon the read/write * mode for other users. */ int dirtype(char *filename, char **dirname) { char *p, *root, fn[MAXSTRLEN]; struct stat status; int type = UNKNOWN; strcpy(fn, filename); root = strchr(fn, DIRSEP); if (root == NULL) fatal("%s: no absolute filename\n"); while ((p = strrchr(fn, DIRSEP)) && p > root) { *p = '\0'; /* Is it an existing directory */ if (pstat(fn, &status) == 0) { if (status.st_uid == eff_uid && private(status.st_mode)) type = PUBLIC_RW; else if (public(status.st_mode)) type = PUBLIC_RW; else if (status.st_uid == real_uid && private(status.st_mode)) type = PRIVATE; else if (readable(status.st_mode)) type = PUBLIC_RO; break; } } *dirname = malloc(strlen(fn) + 1); if (*dirname == NULL) fatal("Out of memory\n"); strcpy(*dirname, fn); return type; } /* forward definition */ #define UINT32 unsigned int int checksum_texfont(char *name, UINT32 *checksum); /* Return name of matching TFM font if any otherwise NULL */ char *matchingtfm(char *pkfile) { char *checksum; UINT32 cspk, cstfm; if (tfmfile == NULL) return NULL; checksum = cfg_value("checksum"); /* do not check */ if (checksum != NULL && strcmp(checksum, "off") == 0) return tfmfile; if (checksum_texfont(pkfile, &cspk) == 0) fatal("%s: can not read checksum\n", pkfile); if (checksum_texfont(tfmfile, &cstfm) == 0) fatal("%s: can not read checksum\n", tfmfile); if (checksum == NULL || strcmp(checksum, "on") == 0) { if (cstfm == cspk) { if (verbose) msg("%s: matching TFM\n", tfmfile); return tfmfile; } else { msg("%s: checksum mismatch\n", tfmfile); return NULL; } } else if (strcmp(checksum, "warn") == 0) { if (cstfm != cspk) msg("%s: checksum mismatch\n", tfmfile); /* PBR */ return tfmfile; } else fatal("checksum = %s: improper value\n", checksum); } #define MAXPATHELEMENTS 16 /* Determine a suitable place where we can install the PK font. We * do this in three passes: * 0) first we look for a PUBLIC cache (if TFM file) * 1) then we look for a PRIVATE cache (if TFM file) * 2) at last we look for a LASTRESORT cache */ char *pkdestination(char *pkfile, char **pkdir) { char *pkdest, *tfmfile, pe[MAXPATHLEN], *ppe, *ppkpath; int pass, type_tfm, npe, maxpe = 0, type_pk[MAXPATHELEMENTS]; char *pk_dir[MAXPATHELEMENTS]; tfmfile = matchingtfm(pkfile); if (tfmfile == NULL) { type_tfm = UNKNOWN; pass = 2; } else if (absname(tfmfile)) { type_tfm = PUBLIC_RO; pass = 0; } else { type_tfm = PRIVATE; pass = 1; } for (pass = pass; pass < 3; pass++) { ppkpath = pkpath; npe = 0; while (*ppkpath) { /* copy next pathelement into pe */ ppe = pe; while (*ppkpath != PATHSEP && *ppkpath != '\0') { #ifdef UNIX if (tilde && *ppkpath == '~') subtilde(&ppe, &ppkpath); else #endif *ppe++ = *ppkpath++; } *ppe = '\0'; if (strchr(pe, '%')) { if (strstr(pe, "%d") && strstr(pe, "%f")) { /* try filename after replacing placeholders */ substitute(pe, "%b%m%f%d%p", bdpi, mode, texfont, dpi, "pk"); } else /* %f and %d are required! */ fatal("%s: incomplete path element!\n", pe); } else { sprintf(ppe, "%c%s.%dpk", DIRSEP, texfont, dpi); } /* determine type and directory for PK destination */ if (npe+1 > maxpe) { maxpe++; if (maxpe == MAXPATHELEMENTS) fatal("Only %d path elements allowed\n", MAXPATHELEMENTS); if (absname(pe)) type_pk[npe] = dirtype(pe, &pk_dir[npe]); else { type_pk[npe] = LASTRESORT; pk_dir[npe] = currentdir; } } if (pass == 0 && type_pk[npe] == PUBLIC_RW) { if (type_tfm == PUBLIC_RO) goto gotone; } if (pass == 1 && type_pk[npe] == PRIVATE) { if (type_tfm == PUBLIC_RO || type_tfm == PRIVATE) goto gotone; } if (pass == 2 && type_pk[npe] == LASTRESORT) goto gotone; if (*ppkpath == PATHSEP) ppkpath++; npe++; } } return NULL; gotone: if (!absname(pe)) { ppe = pe; if (pe[0] == '.' && pe[1] == DIRSEP) ppe+=2; pkdest = malloc(strlen(currentdir)+strlen(ppe)+2); if (pkdest == NULL) fatal("Out of memory\n"); sprintf(pkdest, "%s%c%s", currentdir, DIRSEP, ppe); } else { pkdest = malloc(strlen(pe)+1); if (pkdest == NULL) fatal("Out of memory\n"); strcpy(pkdest, pe); } pkdest_dirtype = type_pk[npe]; *pkdir = pk_dir[npe]; return pkdest; } #define PKPRE 247 #define PKID 89 #define VFID 202 /* * Checksum_texfont() reads the of a TFM file (if filename ends * with ".tfm"), PK file (if magic code equals PK) or or VF file (if magic * code equals VF). Function returns 1 upon succes otherwise (no TFM, PK or * VF file) 0. */ int checksum_texfont(char *name, UINT32 *checksum) { FILE *fontfp; int id, i; if ((fontfp= fopen(name, RB)) == NULL) fatal("%s: can't open file\n", name); if (strcmp(name+strlen(name)-4, ".tfm") ==0) { if (fseek(fontfp, 24L, 0)) { fclose(fontfp); fatal("%s: really a TFM font?\n", name); } *checksum = four(fontfp); /* checksum */ fclose(fontfp); return(1); } /* PK or VF font? */ if (sone(fontfp) != PKPRE) return 0; id = sone(fontfp); if (id == VFID) { /* skip header */ for(i=sone(fontfp); i>0; i--) (void)sone(fontfp) ; *checksum = four(fontfp); /* checksum */ } else if (id == PKID) { /* skip header */ for(i=sone(fontfp); i>0; i--) (void)sone(fontfp) ; (void) four(fontfp); /* design size */ *checksum = four(fontfp); /* checksum */ } else return 0; fclose(fontfp); return(1); } void installfont(char *pkfile) { UINT32 cspk; int i; char *p, *pkdest, *pkdir, dn[MAXSTRLEN], *logfile; struct stat status; void copy(char *pkfile, char *pkdest); if ((pkdest = pkdestination(pkfile, &pkdir)) == NULL) fatal("No suitable place to install %s (left in %s)\n", texfont, forgedir); #ifdef UNIX if (pkdest_dirtype == PUBLIC_RW) { /* Do we need SUID permission? */ if (pstat(pkdir, &status) != 0) fatal("%s: can not stat\n", pkdir); if (status.st_uid == eff_uid) { if (seteuid(eff_uid) == -1) fatal("%s: can't get SUID permissions\n", pkdir); /* No user interrupts */ signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGHUP, SIG_IGN); } } #endif /* make necessary directories */ strcpy(dn, pkdir); i = strlen(dn); p = pkdest + i; while (*p == DIRSEP && (strchr(p+1, DIRSEP) != NULL)) { do { dn[i++] = *p++; } while (*p != DIRSEP && *p != '\0'); if (*p == '\0') break; dn[i] = '\0'; msg("mkdir %s\n", dn); if (mkdir(dn, 0777) == -1) fatal("%s: can not mkdir (%s, 0777)\n", dn, strerror(errno)); } /* copy font (atomic action) */ copy(pkfile, pkdest); if (verbose) msg("%s: installed\n", pkdest); /* log PK font (atomic action) */ logfile = cfg_value("logfile"); if (logfile && pkdest_dirtype == PUBLIC_RW) { int fd_log, len; char message[80]; time_t now; fd_log = open(logfile, O_APPEND | O_WRONLY | O_EXCL, 0664); if (fd_log == -1) fatal("%s: can't open for write (%s)\n", logfile, strerror(errno)); if (time(&now) == -1) fatal("can't get time (%s)\n", strerror(errno)); sprintf(message, "%s", ctime(&now)); sprintf(message+24, " %d %s\n", real_uid, pkdest); len = strlen(message); if (write(fd_log, message, len) == -1) fatal("%s: can't write (%s)\n", logfile, strerror(errno)); close(fd_log); } #ifdef UNIX if (status.st_uid == eff_uid) { if (seteuid(real_uid) == -1) fatal("%s: can't get real-UID permissions\n", pkdir); /* Allow user interrupts */ signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGHUP, SIG_DFL); } #endif clean_up: if (debug != 1 && strcmp(currentdir, forgedir) != 0) { if (chdir(currentdir) == -1) fatal("%s: could not chdir (%s)\n", currentdir, strerror(errno)); cleanup(forgedir); } } #define BUFSIZE 8192 /* * Copy PK file from to its destination . */ void copy(char *pkfile, char *pkdest) { char buf[BUFSIZE]; int N_in, N_out; int fd_in, fd_out; (void) umask(022); /* added by BDR */ #ifdef MSDOS fd_out = open(pkdest, O_CREAT | O_BINARY | O_WRONLY | O_EXCL, 0644); #else fd_out = open(pkdest, O_CREAT | O_WRONLY | O_EXCL, 0644); #endif if (fd_out == -1) fatal("%s: can't open for write (%s)\n", pkdest, strerror(errno)); #ifdef MSDOS fd_in = open(pkfile, O_RDONLY | O_BINARY, 0); #else fd_in = open(pkfile, O_RDONLY, 0); #endif if (fd_in == -1) fatal("%s: can't open for read (%s)\n", pkfile, strerror(errno)); while ((N_in = read(fd_in, buf, BUFSIZE)) > 0) { N_out = write(fd_out, buf, N_in); if (N_out != N_in) { unlink(pkdest); fatal("%s: Write error (%s)\n", pkdest, strerror(errno)); } } if (N_in != 0) { /* no EOF reached */ unlink(pkdest); fatal("%s: write error (%s)\n", pkdest, strerror(errno)); } close(fd_out); close(fd_in); } /* * remove all files in and then the directory itself. */ void cleanup(char *dirname) { char fn[MAXSTRLEN]; struct dirent *de; DIR *D; int n; if ((D = opendir(dirname)) == NULL) fatal("%s: no such directory\n", dirname); /* now remove files */ n = strlen(texfont); while ((de = readdir(D)) != NULL) { if (strncmp(de->d_name, texfont, n) != 0) continue; sprintf(fn, "%s%c%s", dirname, DIRSEP, de->d_name); if (unlink(fn) == -1) msg("%s: can not unlink\n", fn); } closedir(D); /* remove directory if we created one */ if (rm_forgedir) { if (rmdir(dirname) == -1) msg("%s: can not rmdir\n", dirname); else if (verbose) msg("%s: removed\n", dirname); } } /* * This function returns true if is found in . */ int gsfont(char *fontmap, char *psname) { int n, m; char *p, *name, line[MAXSTRLEN]; FILE *FM; FM = pfopen(fontmap, "r"); if (FM == NULL) fatal("%s: can not open\n", fontmap); /* Look for a line of the form: * /Ps-Name (filename.xxx) ; */ n = strlen(psname); while (fgets(line, MAXSTRLEN, FM)) { if (p = strchr(line, '%')) *p = '\0'; if (!(p = strchr(line, '/'))) continue; p++; name = p; m = 0; while (isalnum(*p) || *p == '-') { m++; p++; } if (n == m && strncmp(psname, name, n) == 0) return 1; } return 0; } /* * Function used to search for one single font in FLI path */ int matching(char *font, int size) { if ((strcmp(font, texfont) == 0) && (size == dpi || (size >= dpi-margin && size <= dpi+margin))) return 1; else return 0; } unsigned int unique() { #ifdef UNIX return getpid(); #else /* MSDOS */ { time_t now; unsigned long int next; if (time(&now) == -1) fatal("can't get time (%s)\n", strerror(errno)); return (unsigned int) ((now * 1103515245 + 12345)/65536) % 32768; } #endif }