/*
 * This file is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.  Users
 * may copy or modify this file without charge, but are not authorized to
 * license or distribute it to anyone else except as part of a product
 * or program developed by the user.
 * 
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

#ifndef lint
static char sccsid[] = "@(#)psh.c 9.7 88/02/10 Copyright 1985 Sun Micro";
#endif

/*
 * Copyright (c) 1987 by Sun Microsystems, Inc.
 */

/*-
	PostScript shell
	Used for building applications written entirely
	in PostScript.  Merely takes its stdin and writes
	it to the NeWS server.

 */

#include <stdio.h>
#include "psio.h"
char       *programname;
char       *args[10];
int         nargs;
int         input_file;

PSFILE       *PostScript,
             *PostScriptInput;

#ifndef SYSVREF
processfile(fd)
    register    fd;
{
    int         mask;
    int         mask0;
    int         max;
    int         first = 1;
    int         seen_dollar = 0;
    register PSFILE *outf;
    if (PostScript == 0 && ps_open_PostScript() == 0) {
	fprintf(stderr, "%s: Cannot connect to window server\n",
		programname);
	exit(0);
    }
    outf = PostScript;
    mask0 = 1 << psio_fileno(PostScriptInput);
    max = psio_fileno(PostScriptInput);
    if (fd > max)
	max = fd;
    max++;

    while (1) {
	char        buf[8 * 1024];
	register    n;

	mask = mask0;
	if (fd >= 0) {
	    mask |= 1 << fd;
	}
	psio_flush(outf);
	if (select(max, &mask, 0, 0, 0) < 0)
	{
	    perror(programname);
	    exit(1);
	}
	if (mask & mask0)
	{
	    n = read(psio_fileno(PostScriptInput), buf, sizeof buf);
	    if (n == 0) {
		if (fd >= 0)
		    fprintf(stderr, "%s: NeWS server disconnected\n",
			    programname);
		exit(0);
	    }
	    if (n < 0) {
		perror(programname);
		exit(1);
	    }
	    write(1, buf, n);
	}
	else if (fd >= 0 && (mask & (1 << fd)) != 0)
	{
	    register char *in;
	    n = read(fd, buf, sizeof buf);
	    if (n == 0) {
		psio_fprintf(outf, " quit ");
		close(fd);
		fd = -1;
		continue;
	    }
	    if (n < 0) {
		perror(programname);
		exit(1);
	    }
	    if (buf[0] == '#' && first)
		buf[0] = '%';
	    for (in = buf; --n >= 0; in++) {
		if (seen_dollar) {
		    seen_dollar = 0;
		    if (*in <= '9' && '1' <= *in) {
			register char *in2 = args[*in - '1'];
			if (in2)
			    while (*in2)
				psio_putc(*in2++, outf);
			continue;
		    }
		    if (*in != '$')
			psio_putc('$', outf);
		}
		else if (*in == '$') {
		    seen_dollar++;
		    continue;
		}
		psio_putc(*in, outf);
	    }
	    first = 0;
	}
	else {
	    fprintf(stderr, "%s: bogus read mask %x\n", programname, mask);
	    exit(1);
	}
    }
}
#else
#include <signal.h>
#include <errno.h>

extern int errno;

int showmsg = 1;

terminate()
{
    showmsg = 0;
}

processfile(fd)
    register    fd;
{
    char buf[8 * 1024];
    register    n;
    register PSFILE *outf;
    int pid;

    if (PostScript == 0 && ps_open_PostScript() == 0) {
	fprintf(stderr, "%s: Cannot connect to window server\n",
		programname);
	exit(0);
    }
    outf = PostScript;

    if ((pid = fork()) > 0) {	/* parent */
	signal(SIGCLD, terminate);
	while (n = read(psio_fileno(PostScriptInput), buf, sizeof buf)) {
	    if (n < 0) {
		if (errno == EINTR)
		    continue;
		else {
	            perror(programname);
		    break;
		}
	    }
	    write(1, buf, n);
	}
	if (showmsg) {
	    fprintf(stderr, "%s: NeWS server disconnected\n", programname);
	    signal(SIGCLD, SIG_DFL);
	    kill(pid, SIGKILL);
	}
    } else if (pid == 0) {	/* child */
	int first = 1;
	int seen_dollar = 0;
	register char *in;

	while (n = read(fd, buf, sizeof buf)) {
	    if (n < 0) {
	        perror(programname);
		break;
	    }
	    if (buf[0] == '#' && first)
	        buf[0] = '%';
	    for (in = buf; --n >= 0; in++) {
	        if (seen_dollar) {
		    seen_dollar = 0;
	    	    if (*in <= '9' && '1' <= *in) {
	    	    	register char *in2 = args[*in - '1'];
	    	    	if (in2)
	    		    while (*in2)
	    		    	psio_putc(*in2++, outf);
	    	    	continue;
	    	    }
	    	    if (*in != '$')
			psio_putc('$', outf);
	        }
	        else if (*in == '$') {
		    seen_dollar++;
		    continue;
	        }
	        psio_putc(*in, outf);
	    }
	    first = 0;
	    psio_flush(outf);
	}
	psio_fprintf(outf, " quit ");
	psio_flush(outf);
    } else {
	fprintf(stderr, "%s: fork failure\n", programname);
	exit(1);
    }
}
#endif

main(argc, argv)
    char      **argv;
{
    programname = argv[0];
    while (--argc > 0)
	if ((++argv)[0][0] == '-')
	    switch (argv[0][1]) {
	    default:
		fprintf(stderr, "%s: invalid switch '%s'\n",
			programname, argv[0]);
		exit(1);
	    }
	else if (input_file == 0) {
	    input_file = open(argv[0], 0);
	    if (input_file <= 0) {
		fprintf(stderr, "%s: cannot open %s\n", programname, argv[0]);
		exit(1);
	    }
	}
	else if (nargs < 10)
	    args[nargs++] = argv[0];
	else {
	    fprintf(stderr, "%s: too many arguments\n", programname);
	    exit(1);
	}
    processfile(input_file);
}