#include <stdio.h>
#ifdef SYS5
#include <fcntl.h>
#endif
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include "../../lpc.h"

#define TMPFILE ".lpedit.tmp"
#ifdef SYS5
#define DEFAULT_EDITOR "/lisp/local/bin/emacs"
#else
#define DEFAULT_EDITOR "/usr/local/emacs"
#endif
#define EDITOR "EDITOR"
#define PMODE 0755
#define FLOAT 4
#define INCR 4			/* boundary on which struct items occur */

	char lpbuf[LPBUFSIZ * 2], newbuf[LPBUFSIZ], *lpbufp, editcall[100];
	char syscall[100];
	int lfd, tfd;			/* lp and tmp fd's */
	LPHEADER *lph;
	int tsize, hsize, oldsize;	/* tsize - sizeof text portion */
					/* hsize - new headersize */
					/* oldsize - old headersize */
	int nwrit, nread, totbytes, esize, fsize, framsize, room;
	char *getenv(), *calloc(), *extra;
	
	struct stat filestat;		/* for getting file size */
	
	char *editusage = "usage: lpedit [-e editor] [-f outfile] lpfile";

main(argc, argv)
int argc;
char **argv;
{
	/* Read in a header from an lp file, copy text into temporary file, */
	/* call editor, edit, quit, recopy header and rewrite file */
	
	int i;
	char *cp, c, *outfile, *infile;
	
	if ((argc < 2) || (argc > 6))	{
		fprintf(stderr, "%s\n", editusage);
		exit(1);
	}
	
	infile = argv[--argc];
	argv++;

	while (argc && (cp = *argv) && *cp++ == '-') {
	  while ((c = *cp++) != NULL)
	    switch(c) {
	    case 'e': 
	      strcpy(editcall, *++argv);
	      break;
	    case 'f': 
	      strcpy(outfile, *++argv);
	      break;
	    default:  
	      fprintf(stderr, "%s\n", editusage);
	      exit(1);
	    }
	  argv++;
	}

	if (!outfile) 
		outfile = infile;
	
	if ((lfd = open(infile, O_RDONLY)) <= 0)	{
		fprintf(stderr, "lpedit: can't open file %s\n", infile);
		exit(1);
	}
	
	if ((read(lfd, lpbuf, LPBUFSIZ)) < 0)	{
		fprintf(stderr, "lpedit: error reading header on %s", infile);
		exit(1);
	}

	fstat(lfd, &filestat);			/* get file size */
	lph = (LPHEADER *) lpbuf;
	if (lph->lpmagic != LP_MAGIC)	{
		fprintf(stderr, "lpedit: %s is not an lp file\n", infile);
		exit(1);
	}
	
	tsize = lph->headersize - (lph->text - (char *) lph);	/* textsize */
	fsize = filestat.st_size - lph->headersize;	/* size of data */

	if ((tfd = open(TMPFILE, O_RDWR | O_CREAT | O_TRUNC, PMODE)) <= 0) {
		fprintf(stderr, "lpedit: error opening temporary file\n");
		exit(1);
	}
	
	if ((write(tfd, lph->text, tsize)) < 0)	{
		fprintf(stderr, "lpedit: write to temp file failed\n");
		exit(1);
	}

	close(tfd);
	if (strlen(editcall) == 0)	{
		 strcpy(editcall, getenv(EDITOR));
		 if (strlen(editcall) == 0)
			  strcpy(editcall, DEFAULT_EDITOR); /* call editor */
	}
	strcat(editcall, " ");
	strcat(editcall, TMPFILE);
	system(editcall);

	if ((tfd = open(TMPFILE, O_RDWR)) <= 0)	{
		fprintf(stderr, "lpedit: error opening tmp file after edit\n");
		exit(1);
	}

	if ((tsize = read(tfd, newbuf, LPBUFSIZ)) < 0)	{
		fprintf(stderr, "lpedit: error reading tmp file after edit\n");
		exit(1);
	}

	if (tsize == 0)
		for (i = 0; i < INCR; i++)		/* pad with null */
			lph->text[i] = '\0';

	oldsize = lph->headersize;			/* compute new */
	hsize = (lph->text - (char *) lph) + tsize;	/* headersize */
	esize = INCR - (hsize % INCR);			/* round up to */
	if (esize == INCR) esize = 0;
	if (esize != 0)
		extra = (char *) calloc(esize, sizeof(char)); /* mult. of 4 */

	if ((lseek(tfd, 0, L_SET)) != 0)	{
		fprintf(stderr, "lpedit: error on lseek\n");
		exit(1);
	}

	lph->headersize = hsize + esize;
	if (lph->headersize > LPBUFSIZ) lph->headersize = LPBUFSIZ;

	if ((write(tfd, (char *) lph, lph->text - (char *) lph)) < 0)	{
		fprintf(stderr, "lpedit: error rewriting header\n");
		exit(1);		/* write up to text */
	}

	if ((write(tfd, newbuf, tsize)) < tsize)	{
		fprintf(stderr, "lpedit: error rewriting header\n");
		exit(1);		/* write new text */
	}
	
	if (esize != 0)
		if ((write(tfd, extra, esize)) < esize)	{
			fprintf(stderr, "lpedit: error rewriting header\n");
			exit(1);		/* write filler null's */
		}

	lpbufp = (lpbuf + oldsize);		/* start writing out values */
	framsize = lph->nvals * FLOAT;
	
	for (;;)	{			/* write out file */
		room = ((lpbuf + LPBUFSIZ) - lpbufp);
		if (room <= framsize)	{
			if ((write(tfd, lpbufp, room)) < room)	{
				fprintf(stderr, "lpedit: write error\n");
				exit(1);
			}
			if ((nread = read(lfd, lpbuf, LPBUFSIZ)) < 0)	{
				fprintf(stderr, "lpedit: read error\n");
				exit(1);
			}
			lpbufp = lpbuf;
			if ((write(tfd, lpbufp, framsize - room)) < 
				(framsize - room))	{
				fprintf(stderr, "lpedit: write error\n");
				exit(1);
			}
			lpbufp += (framsize - room);
			totbytes += framsize;
		}
		if ((nwrit = write(tfd, lpbufp, framsize)) <= 0)	{
			fprintf(stderr, "lpedit: write error\n");
			exit(1);
		}
		lpbufp += framsize;
		totbytes += nwrit;
		if (totbytes >= fsize) break;
	}

#ifdef VAX	
	rename(TMPFILE, outfile);			/* rename file */
	unlink(strcat(TMPFILE, ".bak"));	/* cleanup (vax only) */
#endif
#ifdef HP
	strcpy(syscall, "/bin/mv ");
	strcat(syscall, TMPFILE);
	strcat(syscall, " ");
	strcat(syscall, outfile);
	system(syscall);
	unlink(strcat(TMPFILE,"~"));
#endif
}
