/* $Header: /options.c,v 2.5 1999/10/16 18:33:36 Lyle Exp $ */
/*  Copyright Milan Technology Inc. 1991, 1992 */

/* @(#)options.c	2.5 10/16/99 */

/* Fixed bug where you needed to give a space after -P on 04/13/93 */
/* Now you can call it simply from command line as : */
/* fpfilter -P<printer name> <options> */
/* without having to give a space */

/* Modified to support multiple parallel and serial ports for 3200 */
/* Following additional options are now supported : */

/* <no port specified>  - send to port 2000 */
/* <-s>                 - port 2001 */
/* <-p1>                - port 2010 <same as 2000> */
/* <-p2>                - port 2011 <second par port> */
/* <-s1>                - port 2020 <first ser port >
/* <-s2>                - port 2021 <second ser port>
/* Support Adobe Transcript directly,  5/20/94 */
/* additional fpcomm versions: */
/* fpcomm or fpcomm_p1   - parallel1 */
/* fpcomm_s or fpcomm_s1 - serial1 */
/* fpcomm_p2             - parallel2 */
/* fpcomm_s2             - serial2 */
/* <-p3>                 - port 2012 <third par port> */
/* <-p4>                 - port 2013 <fourth par port> */
/* <-pbh>                - convert HP postscript binary file */
/* <-pba>                - convert Adobe postscript binary file */
/* fpcomm_s3             - parallel3 */
/* fpcomm_p2, comm_s2    - set port_index 6/18/97 */
/* fpcomm_p3             - parallel4 */

#include "std.h"
#include "dp.h"
#include "errors.h"

extern char *g_filter_name; /* name by which this program was invoked */
extern char *VERSION;

#ifdef ANSI
void setPortOpt(int dataport)
#else
void setPortOpt(dataport)
int dataport;
#endif
{
  g_opt.dataport = dataport;
  switch( dataport ) {
  case PARALLEL:
  case PARALLEL1:
    g_opt.port_type = PARALLEL_CHAN_TYPE;
    g_opt.port_index = 0;
    strcpy( g_opt.port_id_string,"parallel1" );
    break;
  case SERIAL:
  case SERIAL1:
    g_opt.port_type = SERIAL_CHAN_TYPE;
    g_opt.port_index = 0;
    strcpy( g_opt.port_id_string,"serial1" );
    break;
  case PARALLEL2:
    g_opt.port_type = PARALLEL_CHAN_TYPE;
    g_opt.port_index = 1;
    strcpy( g_opt.port_id_string,"parallel2" );
    break;
  case SERIAL2:
    g_opt.port_type = SERIAL_CHAN_TYPE;
    g_opt.port_index = 1;
    strcpy( g_opt.port_id_string,"serial2" );
    break;
  case PARALLEL3:
    g_opt.port_type = PARALLEL_CHAN_TYPE;
    g_opt.port_index = 2;
    strcpy( g_opt.port_id_string,"parallel3" );
    break;
  case PARALLEL4:
    g_opt.port_type = PARALLEL_CHAN_TYPE;
    g_opt.port_index = 3;
    strcpy( g_opt.port_id_string,"parallel4" );
    break;
  }
}

#ifdef ANSI
void setPostscriptBinary(int binary_type)
#else
void setPostscriptBinary(binary_type)
int binary_type;
#endif
{
  switch( binary_type ) {
  case HP_BINARY:
    if (!g_opt.psbinary_start)
  g_opt.psbinary_start = "\033%-12345X@PJL ENTER LANGUAGE = POSTSCRIPT\n\001M";
    if (!g_opt.psbinary_end)
       g_opt.psbinary_end = "\033%-12345X@PJL ENTER LANGUAGE = PCL\n";
    g_opt.binary_type = HP_BINARY;
    g_opt.chk_ps = 1;
    break;
  case ADOBE_BINARY:
        /* ADOBE_BINARY sends control-d in start_string and end_string */
    if (!g_opt.psbinary_start)
       g_opt.psbinary_start = "\004";
    if (!g_opt.psbinary_end)
       g_opt.psbinary_end = "\004";
    g_opt.binary_type = ADOBE_BINARY;
    g_opt.chk_ps = 1;
    break;
  }
}

#ifdef ANSI
void setDefaults()
#else
void setDefaults()
#endif
{
#if defined (SOLARIS)
   memset(g_opt,(unsigned char)0,sizeof(s_options));
#else
   bzero(g_opt,sizeof(s_options));
#endif
   setPortOpt( PARALLEL );
}

/* ADOBE: checks for those environment variables used by transcript */
/* and sets the relevant option in global option struct */

/* envget is a getenv */
/* 	if variable is not present in the environment or */
/*	it has the null string as value envget returns NULL */
/*	otherwise it returns value from the environment */

#ifdef ANSI
char *envget(char *var)
#else
char *envget(var)
char *var;
#endif
{
    char *val;
    if (!((val = (char*)getenv(var))) || (*val == 0))
    	return((char *) 0);
    else 
       return(val);
}

void parseAdobeEnvironment()
{
   char *test = 0;

   test = envget("BANNERFIRST");
   if (test) {
      g_opt.adobe.banner_first = atoi(test);
      g_opt.dobanner = 1;
   }

   test = envget("BANNERLAST");
   if (test) {
      g_opt.adobe.banner_last = atoi(test);
      g_opt.dobanner = 1;
   }

   test = envget("VERBOSELOG");
   if (test)
      g_opt.adobe.verbose_log = atoi(test);
}

#ifdef ANSI
void handleAdobeArgs(int argc, char **argv)
#else
void handleAdobeArgs(argc, argv)
int argc;
char **argv;
#endif
{
   /* In Transcript we are called like this: */
   /* $PSCOMM -P $pname -p $prog -n $user -h $host $afile */
   /* pscomm gets called with: */
   /*    stdin	== file to print (may be a pipe!) */
   /*    stdout	== printer */
   /*    stderr	== printer log file */
   /*    cwd	== spool directory */
   /*    argv	== set up by interface shell script: */
   /*   filtername	-P printer -p filtername [-r] (don't ever reverse) */
   /*              -n login -h host [accntfile] */
   
   /* parse command-line arguments */
   /* argv (see header comments) comes from the spooler daemon */
   /* itself, so it should be canonical, but at least one 4.2-based */
   /* system uses -nlogin -hhost (insead of -n login -h host) so */
   /* check for both */

   register char *cp;
   char **av = argv;
   g_opt.adobe.prog = *av;
   
   while (--argc) {
      if (*(cp = *++av) == '-') {
	 switch (*(cp + 1)) {
	 case 'P':	/* printer name */
	    argc--;
	    g_opt.adobe.pname = *(++av);
	    break;
	    
	 case 'n':	/* user name */
	    argc--;
	    g_opt.adobe.name = *(++av);
	    break;
	    
	 case 'h':	/* host */
	    argc--;
	    g_opt.adobe.host = *(++av);
	    break;
	    
	 case 'p':	/* prog */
	    argc--;
	    g_opt.adobe.prog = *(++av);
	    break;
	    
	 default:	/* unknown */
	   fprintf(stderr, "%s: unknown option: %s\n", g_opt.adobe.prog, cp);
	   break;
	 }
      }
      else
	 g_opt.adobe.accountingfile = cp;
   }

   /* ADOBE: */
   /* If g_opt.adobe.pname is set then we want to add this */
   /* printer to the list of printers.  But we want this to be */
   /* the lowest priority printer (ask Dan why) and put it last */
   /* after those found in .fpconfig */
   /* So this routine better be called after the .fpconfig */
   /* file is parsed */

   if (g_opt.adobe.pname)
g_opt.prt_list = form_printer_list(g_opt.adobe.pname, g_opt.prt_list, PARALLEL, APPEND);   
}

/* sets g_opt.current_dir if specified on command line (-D) */
#ifdef ANSI
void checkForCurrentDir(int argc, char **argv)
#else
void checkForCurrentDir(argc, argv)
int argc;
char **argv;
#endif
{
   int i = 1;
   while (i < argc) {
    if (argv[i][0] != '-') {
	  i++;
	  continue;
    }
      if (argv[i][1] == 'D') {
	 g_opt.current_dir = argv[i+1];
	 break;
      }
      i++;
   }
}


/* parses command line args and returns "outp_d" flag */

/* We first look into command line option. If a host has been */
/* specified, then we add host to the printer list first. Then look */
/* at host specified in '.fpconfig' file. We add that host to the list. */
/* Finally we look at CLASS, S_CLASS and P_CLASS options and add hosts */
/* accordingly */

#ifdef ANSI
int parseCommandLineArgs(int argc, char **argv)
#else
int parseCommandLineArgs(argc, argv)
int argc;
char **argv;
#endif
{
   int iflag=0, wflag = 0, nflag = 0, lflag = 0, i;
   char *host = 0 ;
   char named[40];

   if ((g_filter_name  = (char *)rindex(argv[0], '/')))
      g_filter_name++;
   else 
      g_filter_name = argv[0];
   
   if ((!(strcmp(g_filter_name, "fpcomm"))) ||
       (!(strcmp(g_filter_name,"fpcomm_p1")))) {
      /* If this is called from Adobe Transcript then we skip the */
      /* rest of the command line handling and just handle the */
      /* regular options that goto pscomm: */
      parseAdobeEnvironment();
      handleAdobeArgs(argc, argv);
      /* return 2 for stderr so that any output back from the */
      /* socket goes to transcript log file */
      return 2;
   }
   if ( ! (strcmp(g_filter_name, "fpcomm_p2"))) {
     setPortOpt( PARALLEL2 );
     parseAdobeEnvironment();
     handleAdobeArgs(argc, argv);
     /* Make sure that the printer type is set to parallel2 */
     if (g_opt.prt_list) {
       g_opt.prt_list->port_type = PARALLEL_CHAN_TYPE;
       g_opt.prt_list->port_index = 1;
       g_opt.prt_list->dataport = PARALLEL2;
     }
     return 2;
   }
   if ( ! (strcmp(g_filter_name, "fpcomm_p3"))) {
     setPortOpt( PARALLEL3 );
     parseAdobeEnvironment();
     handleAdobeArgs(argc, argv);
     /* Make sure that the printer type is set to parallel3 */
     if (g_opt.prt_list) {
       g_opt.prt_list->port_type = PARALLEL_CHAN_TYPE;
       g_opt.prt_list->port_index = 2;
       g_opt.prt_list->dataport = PARALLEL3;
     }
     return 2;
   }
   if ( ! (strcmp(g_filter_name, "fpcomm_p4"))) {
     setPortOpt( PARALLEL4 );
     parseAdobeEnvironment();
     handleAdobeArgs(argc, argv);
     /* Make sure that the printer type is set to parallel4 */
     if (g_opt.prt_list) {
       g_opt.prt_list->port_type = PARALLEL_CHAN_TYPE;
       g_opt.prt_list->port_index = 3;
       g_opt.prt_list->dataport = PARALLEL4;
     }
     return 2;
   }
   if ((!(strcmp(g_filter_name, "fpcomm_s"))) ||
       (!(strcmp(g_filter_name,"fpcomm_s1"))))  {
       /* If this is called from Adobe Transcript then we skip the */
       /* rest of the command line handling and just handle the */
       /* regular options that goto pscomm: */
       setPortOpt( SERIAL );
       parseAdobeEnvironment();
       handleAdobeArgs(argc, argv);
       /* Make sure that the printer type is set to serial */
       if (g_opt.prt_list) {
	 g_opt.prt_list->port_type = SERIAL_CHAN_TYPE;
	 g_opt.prt_list->port_index = 0;
	 g_opt.prt_list->dataport = SERIAL;
       }
       return 2;
     }
   if ( ! (strcmp(g_filter_name, "fpcomm_s2"))) {
       setPortOpt( SERIAL2 );
       parseAdobeEnvironment();
       handleAdobeArgs(argc, argv);
       /* Make sure that the printer type is set to serial */
       if (g_opt.prt_list) {
	 g_opt.prt_list->port_type = SERIAL_CHAN_TYPE;
	 g_opt.prt_list->port_index = 1;
	 g_opt.prt_list->dataport = SERIAL2;
       }
       return 2;
     }
   if ( ! (strcmp(g_filter_name, "parfilter"))) {
      setPortOpt( PARALLEL );
      g_opt.use_control_d = 0;
      g_opt.real_filter = 1;
   } 
   else if ( ! (strcmp(g_filter_name, "pardfilter"))) {
      setPortOpt( PARALLEL );
      g_opt.use_control_d = 1;
      g_opt.real_filter = 1;
   } 
   else if ( ! (strcmp(g_filter_name, "serfilter"))) {
      setPortOpt( SERIAL );
      g_opt.use_control_d = 0;
      g_opt.real_filter = 1;
   } 
   else if ( ! (strcmp(g_filter_name, "serdfilter"))) {
      setPortOpt( SERIAL );
      g_opt.use_control_d = 1;
      g_opt.real_filter = 1;
   } 
   else if ( ! (strcmp(g_filter_name, "psparfilter"))) {
      setPortOpt( PARALLEL );
      g_opt.real_filter = 1;
      g_opt.chk_ps = 1;
   } 
   else if ( ! (strcmp(g_filter_name, "pspardfilter"))) {
      setPortOpt( PARALLEL );
      g_opt.use_control_d = 1;
      g_opt.real_filter = 1;
      g_opt.chk_ps = 1;
   } 
   else if ( ! (strcmp(g_filter_name, "psserfilter"))) {
      setPortOpt( SERIAL );
      g_opt.real_filter = 1;
      g_opt.chk_ps = 1;
   } 
   else if ( ! (strcmp(g_filter_name, "psserdfilter"))) {
      /* code folded from here */
      setPortOpt( SERIAL );
      g_opt.use_control_d = 1;
      g_opt.real_filter = 1;
      g_opt.chk_ps = 1;
      /* unfolding */
   }
   
   i = 1;
   while ((i < argc) && (argv[i][0] == '-')) {
      switch (argv[i][1]) {
      case 'C':
	 if (! strcasecmp(argv[i], "-CLASS")) {
	   /* -CLASS host:port */
g_opt.prt_list = process_class_pair(argv[i+1], g_opt.prt_list, APPEND);
	 }
	 i++;
	 break;

      case 'P':
	 if (! strcasecmp(argv[i], "-P_CLASS")) 
g_opt.prt_list = form_printer_list(argv[i+1], g_opt.prt_list, PARALLEL, APPEND);
	 else {
 	/* If entry next to 'P' which is argv[1] is a blank, then return */
	/* hostname as argv[i+1], else get the name until the next blank */
	/* and return that as the hostname */

			int k = 2; 

			host = (char*) malloc(100);
	    if (argv[i][2] == '\0' )   /* Null term => no more args */
			    host = argv[i+1] ; 
		    else {
 				while (argv[i][k]  != '\0') {
   					host[k-2] = argv[i][k] ;
   					k++;
 				}
                   i-- ;
			  }
           }
	 i++;
	 break;
	 
      case 'S':
	 if (! strcasecmp(argv[i], "-S_CLASS")) 
	    g_opt.prt_list = 
	       form_printer_list(argv[i+1], g_opt.prt_list, SERIAL, APPEND);
	 i++;
	 break;
      case 'c':
	 if (! strcasecmp(argv[i], "-closewait")) 
		g_opt.closewait = 1;
	 break;

      case 'D':
	 g_opt.current_dir = argv[i+1];
	 i++;
	 break;
	 
      case 'A':
	 g_opt.asciifilter = argv[i + 1];
	 g_opt.chk_ps = 1;
	 i++;
	 break;
	 
      case 'i':
	 iflag++;
	 break;
      case 'w':
	 wflag++;
	 break;
      case 'l':
	 lflag++;
	 break;
      case 'd':
#ifdef DATAGEN
	 if (!strcmp(argv[i], "-dataport")) {
	    g_opt.dataport = atoi(argv[i + 1]);
	    i++;
	    break;
	 }
#endif
	 g_opt.use_control_d = 1;
	 break;
      case 'b':
	 g_opt.dobanner = 1;
	 break;
      case 's':
	 if (!strcmp(argv[i], "-startstring")) {
	    g_opt.start_string = parse_string(argv[i + 1]);
	    i++;
	 }
	 else if (! strcmp(argv[i], "-startfile")) {
	    g_opt.send_startfile = 1;
	    strcpy(g_opt.start_file, argv[i + 1]);
	    i++;
	 }
	 else if (! strcasecmp(argv[i], "-sys"))
	    g_opt.notify_type.syslog = 1;
	 else if (! strcasecmp(argv[i], "-s1")) {
	   setPortOpt( SERIAL1 );
	 }
	 else if (! strcasecmp(argv[i], "-s")) {
	   setPortOpt( SERIAL );
	 }
	 else if (! strcasecmp(argv[i], "-s2")) {
	   setPortOpt( SERIAL2 );
	 }
	 else {
	   setPortOpt( SERIAL );
	 }
	 break;
      case 'e':
	 if (!strcmp(argv[i], "-endstring")) {
	    g_opt.end_string = parse_string(argv[i + 1]);
	    i++;
	 }
	 else if (! strcmp(argv[i], "-endfile")) {
	    g_opt.send_endfile = 1;
	    strcpy(g_opt.end_file, argv[i + 1]);
	    i++;
	 }
	 else if (! strcasecmp(argv[i], "-errorfile"))  {
	    g_opt.notify_type.file = 1;
	    strcpy(g_opt.notify_type.filename, argv[i+1]);
	    i++;
	 }
	 break;
      case 'x':
      case 'y':
	 break;
      case 'm':
	 if (!strcmp(argv[i], "-mail")) {
	    g_opt.notify_type.mail = 1;
	    strcpy(g_opt.notify_type.user, argv[i+1]);
	    i++;
	 }
	 else
	    g_opt.mapflg++;	    
	 break;
      case 'n':
	 i++;
	 nflag++;
	 break;
      case 'h':
	 i++;
	 break;
      case 'f':
	 g_opt.ff_flag = 1;
	 break;
      case 'p':
	 if (! strcasecmp(argv[i], "-program"))  {
	    g_opt.notify_type.program = 1; /* Notify thru program */
	    strcpy(g_opt.notify_type.prog_name, argv[i+1]);
	    i++;
	 }
	 else if (! strcmp(argv[i], "-pbh"))
	    setPostscriptBinary( HP_BINARY );
	 else if (! strcmp(argv[i], "-pba"))
	    setPostscriptBinary( ADOBE_BINARY );
	 else if (! strcasecmp(argv[i], "-p1")) {
	   setPortOpt( PARALLEL1 );
	  }
	 else if (! strcasecmp(argv[i], "-p2")) {
	   setPortOpt( PARALLEL2 );
	  }
         else if (! strcasecmp(argv[i], "-p3")) {
           setPortOpt( PARALLEL3 );
          }
         else if (! strcasecmp(argv[i], "-p4")) {
           setPortOpt( PARALLEL4 );
         }
	 else
	    g_opt.chk_ps = 1;
	 break;
      case 'V':
	           fprintf(stderr, "version = %s\n", VERSION);
	           exit(0);
      default:
	           break;
      }
      i++;
   }
   
   if (! nflag ) {
      for (; i < argc; i++) {
	 if (! access(argv[i], R_OK))
	    /* files to read and send across */
	    add_file(&g_opt.file_list, argv[i]);
	 else
	    err_notify(ERR_ILLFILE,0);
      }
   }
   /* If a host has been specified on the command line */
   /* then add this to the FRONT of the list of printers */
   if (host) 
      g_opt.prt_list = 
        form_printer_list(host, g_opt.prt_list, g_opt.dataport, PREPEND);
   return (iflag || wflag || lflag ) ? 2 : 1;   
}
