/* This module allows dvi2vdu to use packed (PK) font format files*/
/* by creating a temporary PXL file from the PK file */
/* The conversion is done by the existing utility pktopx */

/* Marc Hadley.  Kernel Technology Limited.  June 1989 */

#include "def.h"

static char *sccsid[] = "@(#)pkreader.c	1.1";

#define MAXPATHLEN 80

#ifndef TEMPAREA
#define TEMPAREA "/tmp"
#endif /* TEMPAREA */

#ifndef BSD_FILESYSTEM

static short tmpdirmade = FALSE;
static char targetPXLdir[MAXPATHLEN+1];

#include <sys/types.h>
#include <sys/stat.h>

#endif /* BSD_FILESYSTEM */

extern int pktopx();
extern stringvalue fontdir;

FILE * ConvertPKfile ();
int   MakePKname ();
void exitprog ();

typedef struct anode
{
  char *name;
  struct anode *next;
} node, *pnode;

pnode firstfont = NULL;

FILE * ConvertPKfile (fontname)
char  fontname[];
{
  char  sourcePKfile[MAXPATHLEN + 1],
        sourcePKpath[MAXPATHLEN + 1],
        targetPXLpath[MAXPATHLEN + 1];
  char  dummy[11];
  FILE * pkfiletest, *pxlfiletest, *fp;
  char *argarr[3];
  pnode temp;

  if (MakePKname (fontname, sourcePKfile))
    return (NULL);		/* Error in filename */

#ifdef PXLAREA
 /* search for pxl file first */
  (void) sprintf (targetPXLpath, "%s/%s", PXLAREA, fontname);
  pxlfiletest = fopen (targetPXLpath, "r");
  if (pxlfiletest != NULL)
    return pxlfiletest;
#endif

 /* Must create a PXL file from a PK file */

 /* Make pathnames for PK file and temporary PXL file.  If we're lucky */
 /* and have a BSD filesystem supporting long filenames, append the    */
 /* process id to the temp filename to ensure uniqueness.  Otherwise,  */
 /* assume a 14 character filename limit and create a temporarary      */
 /* directory in TEMPAREA in which the PXL files will be created.      */
 /* NOTE that the original idea was that multiple users would be able  */
 /* use each others pre-created fonts, but with strict default         */
 /* permissions, and in a few obscure circumstances, this makes for    */
 /* more trouble that it is worth.                                     */

#ifdef BSD_FILESYSTEM
  (void) sprintf (targetPXLpath, "%s/%s.%d", TEMPAREA, fontname, getpid());
			      /* Add PID suffix to ensure uniqueness */
#else /* USG_FILESYSTEM */
  if(!tmpdirmade)
      (void) mktmpdir("%s/pxlfonts.%d", TEMPAREA, getpid());
  (void) sprintf(targetPXLpath, "%s/pxlfonts.%d/%s",
		  TEMPAREA, getpid(), fontname);
#endif /* BSD_FILESYSTEM */
  
  (void) sprintf (sourcePKpath, "%s/%s", fontdir, sourcePKfile);

 /* check if pxl file has already been created */
  pxlfiletest = fopen (targetPXLpath, "r");
  if (pxlfiletest != NULL)
    return pxlfiletest;

 /* Check if source file exists */
  pkfiletest = fopen (sourcePKpath, "r");
  if (pkfiletest == NULL)
    return (NULL);
  else
    (void) fclose (pkfiletest);

 /* Create temporary PXL file */
  (void) strcpy (dummy, "pktopx");
  argarr[0] = dummy;
  argarr[1] = sourcePKpath;
  argarr[2] = targetPXLpath;

  (void) pktopx (3, argarr);

 /* Save name so PXL file can be deleted later */
  if ((temp = (pnode) malloc (sizeof (node))) == NULL)
  {
    (void) fprintf (stderr, "dvi2vdu: out of memory");
    exitprog (-1);
  }
  temp->next = firstfont;
  temp->name = malloc ((unsigned)(strlen (argarr[2]) + 1));
  if (temp->name == NULL)
  {
    (void) fprintf (stderr, "dvi2vdu: out of memory");
    exitprog (-1);
  }
  (void) strcpy (temp->name, argarr[2]);
  firstfont = temp;

 /* open new file and return handle */
  fp = fopen (argarr[2], "r");
  return (fp);
}

int   MakePKname (pxlname, pkname)
char *pxlname, *pkname;
{
  char *pf, *pk;
  int   XXXX;

 /* pxl file has name in the form fontname.XXXXpxl */
 /* extract XXXX from name */
  pf = pxlname;

  while (*pf != '.' && *pf != '\0')
    *pf++;

  if (*pf == '.')
    *pf++;
  else
    return 1;

  (void) sscanf (pf, "%d", &XXXX);

 /* create PK file name from pxlname */
  pf = pxlname;
  pk = pkname;
  while (*pf != '.')
  {
    *pk++ = *pf++;
  }
  (void) sprintf (pk, ".%dpk", (int) (XXXX / 5.0 + 0.5));

  return 0;
}

void PurgeFonts ()
{
  pnode temp;
  while ((temp = firstfont) != NULL)
  {
    firstfont = firstfont->next;
    (void) unlink (temp->name);
    (void) free (temp->name);
    (void) free ((char *)temp);
  }
}


void exitprog (i)
int   i;
{
  int r_stat;
    
  PurgeFonts ();

#ifndef BSD_FILESYSTEM
  if(tmpdirmade)
      if((r_stat = rmdir(targetPXLdir)) != 0)
	  perror(targetPXLdir);
#endif /* BSD_FILESYSTEM */

  exit (i);
}


#ifndef BSD_FILESYSTEM

#ifndef S_IRWXO
#define S_IRWXO ((unsigned) (S_IREAD | S_IWRITE | S_IEXEC))
#endif /* S_IRWXO */

#ifndef S_IRWXG
#define S_IRWXG (S_IRWXO >> 3)
#endif /* S_IRWXG */

#ifndef S_IRWXU
#define S_IRWXU (S_IRWXO >> 6)
#endif /* S_IRWXU */

mktmpdir (fmt, temparea, pid)
char	*fmt,
	*temparea;
int	pid;
{
	(void) sprintf (targetPXLdir, fmt, temparea, pid);
	if ( mkdir (targetPXLdir, S_IRWXU|S_IRWXG|S_IRWXO) < 0 )
		exitprog (1);
	tmpdirmade = TRUE;
	return;
}


#ifdef NO_DIRCALLS

/* Simulate BSD and V.3 mkdir(2) amd rmdir(2) using system(3) rather than
   mknod(2) and link(2) to avoid need for privilege in this program.
*/

int mkdir(path, mode)
char *path;
int mode;
{
    char cmdbuf[128];

    strcpy(cmdbuf, "mkdir ");
    strcat(cmdbuf, path);

#ifdef DEBUG
    printf("Creating <%s>\n", cmdbuf);
    sleep(2);
#endif /* DEBUG */
    
    if(system(cmdbuf) < 0)
	return -1;
    return chmod(path, mode);
}


int rmdir(path)
char *path;
{
    char cmdbuf[128];
    
    strcpy(cmdbuf, "rmdir ");
    strcat(cmdbuf, path);

#ifdef DEBUG
    printf("Removing <%s>\n", cmdbuf);
    sleep(2);
#endif /* DEBUG */
    
    return system(cmdbuf);
    
}

#endif /* NO_DIRCALLS */

#endif /* BSD_FILESYSTEM */
