/*  make_path_info_string		WJS  Aug 97			*/
/*    The PATH_INFO environment variable contains 4 fields.		*/
/*    This program accepts a string from the first arg on the		*/
/*  command line.  This string consists of up to 3			*/
/*  labelled fields, each describing one of the first 3 of the 4	*/
/*  PATH_INFO fields, immediately followed by the 4th PATH_INFO field	*/
/*  (if any) which is NOT labelled.  At present, the 4th already	*/
/*  contains labelled information, so the effect will be to accept a	*/
/*  string containing an indefinite amount of labelled information.	*/
/*  Labelled fields MUST precede the unlabelled field.			*/
/*    A labelled field is of the form					*/
/*		label=field						*/
/*  The labelled fields are separated by commas.  The assumption is	*/
/*  that no field contains a comma or an equal sign.  The labels are	*/
/*  object, protocol, and level.  Empty fields are required if the	*/
/*  corresponding field in PATH_INFO is to be empty.  (eg, the		*/
/*  the input string would contain "label=").  Missing fields mean	*/
/*  that the corresponding field in the existing PATH_INFO should be	*/
/*  used.								*/
/*    The use of equal signs and commas is tied to the assumed format	*/
/*  of the 4th field, again in hopeful anticipation...			*/
/*									*/
/*    The program writes a "PATH_INFO" string, followed by a newline,	*/
/*  to stdout.  The newline can be suppressed by using the -nonewline	*/
/*  switch.								*/
/*    Program exits:							*/
/*	  (defined in path_info_routines.h - check there if these	*/
/*	   values seem wrong in case they've changed...)		*/
/*	  0	OK							*/
/*	250	final PATH_INFO string is improper in content or	*/
/*		format, or there was trouble getting dynamic memory	*/
/*	251	badly formatted input (must be an = in each pair)	*/
/*	252	duplicated labelled field (among the 1st 3 fields)	*/
/*	253	level has non-numeric character in it			*/
/*	254	Bad input switch; > 1 input string			*/
/*									*/
/*    Example:  if make_path_info_string gets				*/
/*	object=//gb1.whoi.edu/test,protocol=html,level=0,dir=xx,info=yy	*/
/*    it will write the string						*/
/*	//gb1.whoi.edu/test.html0{dir=xx,info=yy}			*/
/*									*/
/*    See the path_info_routines.c file for more information		*/

#define MAKE_PATH_INFO_ID "make_path_info_string version 1.3 25 Apr 2004"
/* 25 Apr 04  v 1.3			WJS				*/
/*	Made this a "major" release to avoid "numbering" problems.	*/
/*	  Orig packaging got its version from path_info_routines.c,	*/
/*	  which changed faster than its calling routines like this one	*/
/*	  W/that program now packaged w/the library, not clear what	*/
/*	  the version of THIS package should be...			*/
/* 11 Feb 04  v 1.3			WJS				*/
/*	Fixes to avoid compiler warnings				*/
/*	    [Begin 1.3]							*/
/* 18 Jul 99  v 1.2a			WJS				*/
/*	Allow -no as a synonym for -nonewline				*/
/*	Bug fix: -nonewline output had a concluding \0 as part of it	*/
/*	    [Begin 1.2a]						*/
/* 20 Apr 99  v 1.2			WJS				*/
/*	-nonewline switch						*/
/*	New exit statuses						*/
/*	    [Needs path_info_routines.c v 1.2]				*/
/*	    [Needs path_info_routines.h v 1.3]				*/
/*	    [Begin 1.2]							*/
/* 17 Sep 97  v 1.1			WJS				*/
/*	Move error defns to .h file					*/
/*	Correct documentation about error returns			*/
/*	    [Needs path_info_routines.c v 1.2; .h v 1.2]		*/
/*	    [Begin 1.1]							*/
/* 29 Aug 97  v 1.0			WJS				*/
/*	    [Needs path_info_routines.c v 1.2; .h v 1.1]		*/
/*	    [Begin 1.0]							*/

  /*  Force version string into object files				*/
char *make_path_info_id = MAKE_PATH_INFO_ID;

#include "path_info_routines.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_DEFINED_PAIRS 3	/* object, protocol, level		*/

  /*  path_info_routines						*/
char *make_PATH_INFO_putenv_string();

int main(argc,argv)
int argc;
char *argv[];
{
  char *ptr,*end_ptr,*ptr2,*term_char;
  char *inbuf = NULL;

  int npairs = 0;

    /*  Init fields to "use what's in existing PATH_INFO"		*/
  char *object_ptr = NULL;
  char *protocol_ptr = NULL;
  char *options_ptr = NULL;
  int level = USE_EXISTING_LEVEL;

  char *output_terminator = "\n";
  int i;

  for (i = 1; i < argc; i++)
    if (*argv[i] == '-') {
      if (  (strcmp(argv[i],"-no") == 0)	||
	    (strcmp(argv[i],"-nonewline") == 0)   )
        output_terminator[0] = '\0';
      else {
	printf ("***ERROR*** illegal switch: %s\n",argv[i]);
	exit(BAD_ARGS);
      }
    } else {
      if (inbuf != NULL) {
	printf ("***ERROR*** > 1 input param: %s %s\n",inbuf,argv[i]);
	exit(BAD_ARGS);
      }
      inbuf = argv[i];
    }

  ptr = inbuf;
  while (ptr != NULL) {
      /*  Need to count pairs in case 4th field contains a duplicate	*/
      /*  label to 1st 3.  For example, a legit PATH_INFO of		*/
      /*  	obj.html0{object=doofus}				*/
      /*  would have input of						*/
      /*  	object=obj,protocol=html,level=0,object=doofus		*/
      /*  Note problem in future over duplicate labels; note problem	*/
      /*  in present code in this case if one of 1st 3 fields missing	*/
      /*	obj.html{object=doofus}					*/
      /*  would have input of						*/
      /*	object=obj,protocol=html,object=doofus			*/
      /*  and would produce an error.					*/
    if (++npairs > MAX_DEFINED_PAIRS) {
      options_ptr = ptr;
      break;
    }

      /*  Chop at next comma, if any					*/
    end_ptr = strchr(ptr,PATH_INFO_OPTIONS_SEPARATOR_CHAR);
    if (end_ptr != NULL) *end_ptr = '\0';

    ptr2 = strchr(ptr,PATH_INFO_OPTIONS_DEFN_CHAR);
      /*  Cannot immediately error if = missing, since at present	*/
      /*  there is no requirement for 4th field to have =s.  Eg		*/
      /*  a PATH_INFO of						*/
      /*	obj.html{description}					*/
      /*  would come from input of					*/
      /*	object=obj,protocol=html,description			*/
      /*  with legit missing = in 3rd input "pair"			*/

      /*  Replace = with '\0' to divide token into label & field	*/
    if (ptr2 != NULL) *(ptr2++) = '\0';

    if (strcmp("object",ptr) == 0) {
      if (object_ptr != NULL) exit(DUP_LABEL);
      if (ptr2 == NULL) exit(MISSING_EQUAL);
      object_ptr = ptr2;
    } else if (strcmp("protocol",ptr) == 0) {
      if (protocol_ptr != NULL) exit(DUP_LABEL);
      if (ptr2 == NULL) exit(MISSING_EQUAL);
      protocol_ptr = ptr2;
    } else if (strcmp("level",ptr) == 0) {
      if (level != USE_EXISTING_LEVEL) exit(DUP_LABEL);
      if (ptr2 == NULL) exit(MISSING_EQUAL);
      if (*ptr2 == '\0') level = LEVEL_NOT_SPECIFIED;
      else {
	level = strtol(ptr2,&term_char,10);
	if (*term_char != '\0') exit(NON_NUMERIC_LEVEL);
      }
    } else {
	/*  Unrecognized label means beginning of options string	*/
	/*  We're done parsing; restore = and , then go			*/
      if (ptr2 != NULL) *(--ptr2) = PATH_INFO_OPTIONS_DEFN_CHAR;
      if (end_ptr != NULL) *end_ptr = PATH_INFO_OPTIONS_SEPARATOR_CHAR;
      options_ptr = ptr;
      break;
    }

    ptr = (end_ptr == NULL) ? NULL : end_ptr+1;
  }

    /*  Do it!								*/
    /*   "" = don't put "PATH_INFO=" in front of result			*/
    /*	 NULL means use existing PATH_INFO for defaults			*/
  ptr = make_PATH_INFO_putenv_string
		("",NULL,object_ptr,protocol_ptr,level,options_ptr);
  if (ptr == NULL) exit(BAD_MAKE_PATH_INFO);
  printf ("%s%s",ptr,output_terminator);
  exit(0);
}
