/* Copyright (C) 2000 Free Software Foundation.  All rights reserved.
  
  This file is part of GNU Ghostscript.
  
  GNU Ghostscript is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility to
  anyone for the consequences of using it or for whether it serves any
  particular purpose or works at all, unless he says so in writing.  Refer to
  the GNU General Public License for full details.
  
  Everyone is granted permission to copy, modify and redistribute GNU
  Ghostscript, but only under the conditions described in the GNU General
  Public License.  A copy of this license is supposed to have been given to
  you along with GNU Ghostscript so you can know your rights and
  responsibilities.  It should be in a file named COPYING.  Among other
  things, the copyright notice and this notice must be preserved on all
  copies.
  
  Aladdin Enterprises is not affiliated with the Free Software Foundation or
  the GNU Project.  GNU Ghostscript, as distributed by Aladdin Enterprises,
  does not depend on any other GNU software.

  However Display Ghostscript System depends on GLib. */

/* $Id: dgs.c,v 1.3 2000/03/27 15:57:24 cigas Exp $ */
/* Main program for display ghostscript system dgs/dpsnx.agent */

#include "string_.h"

/*  This currently causes all kinds of conflicts - we'll duplicate the
one definition we need here 
#include "dgs.h" 
*/
#include "DPS/dpsNXargs.h"
enum conn_type
{ UNIXCONN = XDPSNX_TRANS_UNIX, TCPCONN = XDPSNX_TRANS_TCP };

/* This should be in its own header file, but dgs.c and dgsserve.c may merge. */
int start_dpsnx_server(int argc, char *argv[]);

/* Should work to eliminate these */
int DGS_DEBUG = 0;
int DGS_PORT = 0;

/* Connection type was NOT settable in dgs 0.5.9.1 ?!?!? */
enum conn_type DGS_TRANSPORT = UNIXCONN;

private int args_get_port(const char *args);

#include <stdio.h>
#include <unistd.h>
#include <getopt.h>

#include <stdlib.h>

enum arg_flags
{ LO_NOP, LO_DEBUG, LO_HELP, LO_LINGER, LO_NOLOG, LO_PORT,
    LO_PSRES, LO_QUANTUM, LO_STACK, LO_SYNC, LO_TRANSPORT, LO_VERSION
};

int
main(int argc, char *argv[])
{
    static char usage[] =
	"Usage: dpsnx.agent [dgs options] [-- gs options]\n"
	"   dgs options are as follows:\n"
	"   --help                Print this message\n"
	"   --debug=N             Wait N seconds before forking dgs agent\n"
	"                         and enable printing of debug messages.\n"
	"   --port=N              Listen for clients on port N\n"

	"   --transport=tcp|unix  Use this transport protocol\n"
	"   --version             Print version information\n";
    static char copyright[] =
	"Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.\n"
	"You may redistribute copies of GNU Display Ghostscript System\n"
	"under the terms of the GNU General Public License.\n"
	"For more information about these matters, see the file named COPYING."

	"\n";
    char shortopts[] = "";
    struct option longopts[] = {
	{"debug", required_argument, 0, LO_DEBUG},
	{"help", no_argument, 0, LO_HELP},
	{"linger", required_argument, 0, LO_LINGER},
	{"nolog", no_argument, 0, LO_NOLOG},
	{"port", required_argument, 0, LO_PORT},
	{"psres", required_argument, 0, LO_PSRES},
	{"quantum", required_argument, 0, LO_QUANTUM},
	{"stack", required_argument, 0, LO_STACK},
	{"sync", no_argument, 0, LO_SYNC},
	{"transport", required_argument, 0, LO_TRANSPORT},
	{"version", no_argument, 0, LO_VERSION},
	{(char *)0, no_argument, (int *)0, 0}
    };

    int c = 0;
    int option_index = 0;
    char *progname = NULL;

    while ((c = getopt_long(argc, argv, shortopts, longopts, &option_index))
	   != -1) {
	switch (c) {
	    case LO_DEBUG:
		sscanf(optarg, "%d", &DGS_DEBUG);
		if (DGS_DEBUG < 0) {
		    fprintf(stderr, "Debug value (%d) must be non-negative\n",
			    DGS_DEBUG);
		    exit(1);
		}
		break;
	    case LO_HELP:
		fprintf(stderr, usage);
		exit(0);
	    case LO_LINGER:
		fprintf(stderr,
			"This version of %s lingers forever and must be explicitly killed\n",
			argv[0]);
		break;
	    case LO_PORT:
		sscanf(optarg, "%d", &DGS_PORT);
		if (DGS_PORT < 0) {
		    fprintf(stderr, "Port value (%d) must be non-negative\n",
			    DGS_PORT);
		    exit(1);
		}
		break;
	    case LO_TRANSPORT:
		fprintf(stderr,
			"Explicit transport assignment may not be working\n");
		if (strcmp(optarg, "tcp") == 0)
		    DGS_TRANSPORT = TCPCONN;
		else if (strcmp(optarg, "unix") != 0) {
		    fprintf(stderr, "Unknown transport \"%s\"\n", optarg);
		    exit(1);
		}
		break;
	    case LO_VERSION:
		fprintf(stderr,
			"GNU Display Ghostscript System %s based on Ghostscript %s\n",
			VERSION, GS_VERSION);
		fprintf(stderr, copyright);
		exit(0);
	    case ':':
	    case '?':
		break;
	    default:
		fprintf(stderr, "Option \"%s\" not yet implemented\n",
			longopts[option_index].name);
		break;
	}
    }
    /* Check for dpsnx.agent to start server processes */
    progname = strrchr(argv[0], '/');
    if (progname == NULL)
	progname = argv[0];
    else
	progname++;

    if (DGS_DEBUG) {
	fprintf(stderr, "program name = %s\n", progname);
	if (optind < argc) {
	    int i = optind;

	    while (i < argc)
		fprintf(stderr, "gs arg = %s\n", argv[i++]);
	}
	fprintf(stderr, "dgs: argc = %d\t\toptind = %d\n", argc, optind);
    }

    /* Check for "tcp/N" passed from client library autolaunching */

    if (optind < argc) {
	DGS_PORT = args_get_port(argv[optind]);
	if (DGS_PORT)
	    optind++;
    }

    if (strcmp(progname, "dpsnx.agent") == 0) {
	/* set GS_OPTIONS - check first for existing ones */
	char *gs_opt_p = NULL;
	char *new_gs_opt_p = NULL;
	const char *dgs_gs_options =

	    "GS_OPTIONS=-q -DNODISPLAY -DQUIET -DDGS";

	if ((gs_opt_p = getenv("GS_OPTIONS")) != NULL) {
	    if (DGS_DEBUG) {
		fprintf(stderr, "Warning: Found GS_OPTIONS=\"%s\"\n",
			gs_opt_p);
		fprintf(stderr,
			"  May override Display Ghostscript defaults\n");
	    }
	    new_gs_opt_p =
		(char *)malloc(strlen(gs_opt_p) + strlen(dgs_gs_options) + 2);
	    if (new_gs_opt_p == NULL) {
		fprintf(stderr,
			"Can't allocate space for environment GS_OPTIONS\n");
		exit(1);
	    }
	    sprintf(new_gs_opt_p, "%s %s", dgs_gs_options, gs_opt_p);
	    putenv(new_gs_opt_p);
	    if (DGS_DEBUG)
		fprintf(stderr, "Using GS_OPTIONS=\"%s\"\n", new_gs_opt_p);
	} else
	    putenv(dgs_gs_options);

	/* gs_main_init_with_args skips the first argument - add one back */
	start_dpsnx_server(argc - optind + 1, &argv[optind-1]);
    } else {
	/* Just create an interpreter and pass arguments */
	fprintf(stderr,
		"Entry points besides \"dpsnx.agent\" not yet defined.\n");
    }
    return 0;
}

/* This sets DGS_TRANSPORT as a side effect, but DGS_TRANSPORT is not
 *  used in dgs-0.5.9
 */
/* Return 0 if the port is not specified */
private int
args_get_port(const char *args)
{
    const char *unix_str = strstr(args, "unix/");
    const char *tcp_str = strstr(args, "tcp/");
    const char *decnet_str = strstr(args, "decnet/");
    const char *tmp;
    const char *port_str;
    int port;

    if (decnet_str != NULL) {
	fprintf(stderr, "decnet is not supported.\n");
	return 0;
    } else if (unix_str != NULL) {
	tmp = strchr(unix_str, '/');
	DGS_TRANSPORT = UNIXCONN;
    } else if (tcp_str != NULL) {
	tmp = strchr(tcp_str, '/');
	DGS_TRANSPORT = TCPCONN;
    } else
	return 0;

    if ((!tmp) || (tmp[1] == '\0'))
	return 0;

    port_str = tmp + 1;
    port = atoi(port_str);
    if (DGS_DEBUG)
	fprintf(stderr,
		"Passed port[%d] via autolaunch command line.\n", port);

    return port;
}
