<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"
#include "condor_distribution.h"
#include "dc_collector.h"
#include "dc_schedd.h"
#include "get_daemon_name.h"
#include "internet.h"
#include "print_wrapped_text.h"
#include "MyString.h"
#include "metric_units.h"
#include "ad_printmask.h"
#include "directory.h"
#include "iso_dates.h"
#include "basename.h" // for condor_dirname
#include "match_prefix.h"
#include "subsystem_info.h"
#include "historyFileFinder.h"
#include "condor_id.h"
#include "userlog_to_classads.h"

#include "history_utils.h"
#include "backward_file_reader.h"
#include <fcntl.h>  // for O_BINARY

#ifdef HAVE_EXT_POSTGRESQL
#include "sqlquery.h"
#include "historysnapshot.h"
#define NUM_PARAMETERS 3
#endif /* HAVE_EXT_POSTGRESQL */

static int getConsoleWindowSize(int * pHeight = NULL);
void Usage(char* name, int iExitCode=1);

void Usage(char* name, int iExitCode) 
{
	printf ("Usage: %s [source] [restriction-list] [options]\n"
		"\n   where [source] is one of\n"
		"\t-file <file>\t\tRead history data from specified file\n"
		"\t-userlog <file>\t\tRead job data specified userlog file\n"
		"\t-name <schedd-name>\tRemote schedd to read from\n"
		"\t-pool <collector-name>\tPool remote schedd lives in.\n"
		"   If neither -pool, -name, -userlog or -file is specified, then the local history file is used.\n"
#ifdef HAVE_EXT_POSTGRESQL
		"\t-dbname <schedd-name>\tRead history data from Quill database\n"
		"\t-completedsince <time>\tDisplay jobs completed on/after time\n"
#endif
		"\n   and [restriction-list] is one or more of\n"
		"\t<cluster>\t\tGet information about specific cluster\n"
		"\t<cluster>.<proc>\tGet information about specific job\n"
		"\t<owner>\t\t\tInformation about jobs owned by <owner>\n"
		"\t-constraint <expr>\tInformation about jobs matching <expr>\n"
		"\n   and [options] are one or more of\n"
		"\t-help\t\t\tDisplay this screen\n"
		"\t-backwards\t\tList jobs in reverse chronological order\n"
		"\t-forwards\t\tList jobs in chronological order\n"
		"\t-limit <number>\t\tLimit the number of jobs displayed\n"
		"\t-match <number>\t\tOld name for -limit\n"
		"\t-long\t\t\tDisplay entire classads\n"
		"\t-wide[:<width>]\tcon\tDon't truncate fields to fit into 80 columns\n"
		"\t-format <fmt> <attr>\tDisplay attr using printf formatting\n"
		"\t-autoformat[:lhVr,tng] <attr> [<attr2 ...]   Display attr(s) with automatic formatting\n"
		"\t-af[:lhVr,tng] <attr> [<attr2 ...]\t    Same as -autoformat above\n"
		"\t    where the [lhVr,tng] options influence the automatic formatting:\n"
		"\t    l\tattribute labels\n"
		"\t    h\tattribute column headings\n"
		"\t    V\t%%V formatting (string values are quoted)\n"
		"\t    r\t%%r formatting (raw/unparsed values)\n"
		"\t    t\ttab before each value (default is space)\n"
		"\t    g\tnewline between ClassAds, no space before values\n"
		"\t    ,\tcomma after each value\n"
		"\t    n\tnewline after each value\n"
		"\t    use -af:h to get tabular values with headings\n"
		"\t-print-format <file>\tUse <file> to specify the attributes and formatting\n"
		"\t\t\t\t(experimental, see htcondor-wiki for more information)\n"
		, name);
  exit(iExitCode);
}

#ifdef HAVE_EXT_POSTGRESQL
static char * getDBConnStr(char *&quillName, char *&databaseIp, char *&databaseName, char *&queryPassword);
static bool checkDBconfig();
static	QueryResult result;
#endif /* HAVE_EXT_POSTGRESQL */

static void readHistoryRemote(classad::ExprTree *constraintExpr);
static void readHistoryFromFiles(bool fileisuserlog, const char *JobHistoryFileName, const char* constraint, ExprTree *constraintExpr);
static void readHistoryFromFileOld(const char *JobHistoryFileName, const char* constraint, ExprTree *constraintExpr);
static void readHistoryFromFileEx(const char *JobHistoryFileName, const char* constraint, ExprTree *constraintExpr, bool read_backwards);
static void printJobAds(ClassAdList & jobs);
static void printJob(ClassAd & ad);

static int set_print_mask_from_stream(AttrListPrintMask & print_mask, std::string & constraint, const char * streamid, bool is_filename);
static int getDisplayWidth();


//------------------------------------------------------------------------

static CollectorList * Collectors = NULL;
#ifdef HAVE_EXT_POSTGRESQL
static	CondorQuery	quillQuery(QUILL_AD);
static	ClassAdList	quillList;
#endif
static  bool longformat=false;
static  bool diagnostic = false;
static  bool use_xml=false;
static  bool wide_format=false;
static  int  wide_format_width = 0;
static  bool customFormat=false;
static  bool disable_user_print_files=false;
static  bool backwards=true;
static  AttrListPrintMask mask;
//tj: headings moved into the mask object.
//static  List<const char> headings; // The list of headings for the mask entries
static int cluster=-1, proc=-1;
static int specifiedMatch = 0, matchCount = 0;
static std::string g_name, g_pool;

int
main(int argc, char* argv[])
{
  Collectors = NULL;

#ifdef HAVE_EXT_POSTGRESQL
  HistorySnapshot *historySnapshot;
  SQLQuery queryhor;
  SQLQuery queryver;
  QuillErrCode st;
  bool remotequill=false;
  char *quillName=NULL;
  AttrList *ad=0;
  int flag = 1;
  void **parameters;
  char *dbconn=NULL;
  char *completedsince = NULL;
  char *dbIpAddr=NULL, *dbName=NULL,*queryPassword=NULL;
  bool remoteread = false;
#endif /* HAVE_EXT_POSTGRESQL */

  const char *owner=NULL;
  bool readfromfile = true;
  bool fileisuserlog = false;

  char* JobHistoryFileName=NULL;
  const char * pcolon=NULL;


  GenericQuery constraint; // used to build a complex constraint.
  ExprTree *constraintExpr=NULL;

  std::string tmp;

  int i;
  myDistro->Init( argc, argv );

  config();

#ifdef HAVE_EXT_POSTGRESQL
  parameters = (void **) malloc(NUM_PARAMETERS * sizeof(void *));
  queryhor.setQuery(HISTORY_ALL_HOR, NULL);
  queryver.setQuery(HISTORY_ALL_VER, NULL);
#endif /* HAVE_EXT_POSTGRESQL */

  for(i=1; i<argc; i++) {
    if (is_dash_arg_prefix(argv[i],"long",1)) {
      longformat=TRUE;   
    }
    
    else if (is_dash_arg_prefix(argv[i],"xml",3)) {
		use_xml = true;	
		longformat = true;
	}
    
    else if (is_dash_arg_prefix(argv[i],"backwards",1)) {
        backwards=TRUE;
    }

	// must be at least -forw to avoid conflict with -f (for file) and -format
    else if (is_dash_arg_prefix(argv[i],"nobackwards",3) ||
			 is_dash_arg_prefix(argv[i],"forwards",4)) {
        backwards=FALSE;
    }

    else if (is_dash_arg_colon_prefix(argv[i],"wide", &pcolon, 1)) {
        wide_format=TRUE;
        if (pcolon) {
            wide_format_width = atoi(++pcolon);
            if ( ! mask.IsEmpty()) mask.SetOverallWidth(getDisplayWidth()-1);
            if (wide_format_width <= 80) wide_format = FALSE;
        }
    }

    else if (is_dash_arg_prefix(argv[i],"match",1) || is_dash_arg_prefix(argv[i],"limit",3)) {
        i++;
        if (argc <= i) {
            fprintf(stderr,
                    "Error: Argument -match requires a number value "
                    " as a parameter.\n");
            exit(1);
        }
        specifiedMatch = atoi(argv[i]);
    }

#ifdef HAVE_EXT_POSTGRESQL
    else if(is_dash_arg_prefix(argv[i], "dbname",1)) {
		i++;
		if (argc <= i) {
			fprintf( stderr,
					 "Error: Argument -dbname requires the name of a quilld as a parameter\n" );
			exit(1);
		}
		

/*
		if( !(quillName = get_daemon_name(argv[i])) ) {
			fprintf( stderr, "Error: unknown host %s\n",
					 get_host_part(argv[i]) );
			printf("\n");
			print_wrapped_text("Extra Info: The name given with the -dbname "
							   "should be the name of a condor_quilld process. "
							   "Normally it is either a hostname, or "
							   "\"name@hostname\". "
							   "In either case, the hostname should be the "
							   "Internet host name, but it appears that it "
							   "wasn't.",
							   stderr);
			exit(1);
		}
		sprintf (tmp, "%s == \"%s\"", ATTR_NAME, quillName);      		
		quillQuery.addORConstraint (tmp);

*/
		quillName = argv[i];

		sprintf (tmp, "%s == \"%s\"", ATTR_SCHEDD_NAME, quillName);
		quillQuery.addORConstraint (tmp.c_str());

		remotequill = false;
		readfromfile = false;
    }
#endif /* HAVE_EXT_POSTGRESQL */
    else if (is_dash_arg_prefix(argv[i],"file",2)) {
		if (i+1==argc || JobHistoryFileName) break;
		i++;
		JobHistoryFileName=argv[i];
		readfromfile = true;
    }
	else if (is_dash_arg_prefix(argv[i],"userlog",1)) {
		if (i+1==argc || JobHistoryFileName) break;
		i++;
		JobHistoryFileName=argv[i];
		readfromfile = true;
		fileisuserlog = true;
	}
    else if (is_dash_arg_prefix(argv[i],"help",1)) {
		Usage(argv[0],0);
    }
    else if (is_dash_arg_prefix(argv[i],"format",1)) {
		if (argc <= i + 2) {
			fprintf(stderr,
					"Error: Argument -format requires a spec and "
					"classad attribute name as parameters.\n");
			fprintf(stderr,
					"\t\te.g. condor_history -format '%%d' ClusterId\n");
			exit(1);
		}
		mask.registerFormat(argv[i + 1], argv[i + 2]);
		customFormat = true;
		i += 2;
    }
	else if (*(argv[i]) == '-' && 
				(is_arg_colon_prefix(argv[i]+1,"af", &pcolon, 2) ||
				 is_arg_colon_prefix(argv[i]+1,"autoformat", &pcolon, 5))) {
		// make sure we have at least one argument to autoformat
		if (argc <= i+1 || *(argv[i+1]) == '-') {
			fprintf (stderr, "Error: Argument %s requires at last one attribute parameter\n", argv[i]);
			fprintf(stderr, "\t\te.g. condor_history %s ClusterId\n", argv[i]);
			exit(1);
		}
		if (pcolon) ++pcolon; // if there are options, skip over the colon to the options.
		int ixNext = parse_autoformat_args(argc, argv, i+1, pcolon, mask, diagnostic);
		if (ixNext > i)
			i = ixNext-1;
		customFormat = true;
	}
	else if (is_dash_arg_colon_prefix(argv[i], "print-format", &pcolon, 2)) {
		if ( (argc <= i+1)  || (*(argv[i+1]) == '-' && (argv[i+1])[1] != 0)) {
			fprintf( stderr, "Error: Argument -print-format requires a filename argument\n");
			exit( 1 );
		}
		// hack allow -pr ! to disable use of user-default print format files.
		if (MATCH == strcmp(argv[i+1], "!")) {
			++i;
			disable_user_print_files = true;
			continue;
		}
		if ( ! wide_format) mask.SetOverallWidth(getDisplayWidth()-1);
		customFormat = true;
		++i;
		std::string where_expr;
		if (set_print_mask_from_stream(mask, where_expr, argv[i], true) < 0) {
			fprintf(stderr, "Error: cannot execute print-format file %s\n", argv[i]);
			exit (1);
		}
		if ( ! where_expr.empty()) {
			constraint.addCustomAND(where_expr.c_str());
		}
	}
    else if (is_dash_arg_prefix(argv[i],"constraint",1)) {
		// make sure we have at least one more argument
		if (argc <= i+1) {
			fprintf( stderr, "Error: Argument %s requires another parameter\n", argv[i]);
			exit(1);
		}
		i++;
		constraint.addCustomAND(argv[i]);
    }
#ifdef HAVE_EXT_POSTGRESQL
    else if (is_dash_arg_prefix(argv[i],"completedsince",3)) {
		i++;
		if (argc <= i) {
			fprintf(stderr,
					"Error: Argument -completedsince requires a date and "
					"optional timestamp as a parameter.\n");
			fprintf(stderr,
					"\t\te.g. condor_history -completedsince \"2004-10-19 10:23:54\"\n");
			exit(1);
		}
		
		if (constraint!="") break;
		completedsince = strdup(argv[i]);
		parameters[0] = completedsince;
		queryhor.setQuery(HISTORY_COMPLETEDSINCE_HOR,parameters);
		queryver.setQuery(HISTORY_COMPLETEDSINCE_VER,parameters);
    }
#endif /* HAVE_EXT_POSTGRESQL */

    else if (sscanf (argv[i], "%d.%d", &cluster, &proc) == 2) {
		std::string jobconst;
		formatstr (jobconst, "%s == %d && %s == %d", 
				 ATTR_CLUSTER_ID, cluster,ATTR_PROC_ID, proc);
		constraint.addCustomOR(jobconst.c_str());
		#ifdef HAVE_EXT_POSTGRESQL
		parameters[0] = &cluster;
		parameters[1] = &proc;
		queryhor.setQuery(HISTORY_CLUSTER_PROC_HOR, parameters);
		queryver.setQuery(HISTORY_CLUSTER_PROC_VER, parameters);
		#endif /* HAVE_EXT_POSTGRESQL */
    }
    else if (sscanf (argv[i], "%d", &cluster) == 1) {
		std::string jobconst;
		formatstr (jobconst, "%s == %d", ATTR_CLUSTER_ID, cluster);
		constraint.addCustomOR(jobconst.c_str());
		#ifdef HAVE_EXT_POSTGRESQL
		parameters[0] = &cluster;
		queryhor.setQuery(HISTORY_CLUSTER_HOR, parameters);
		queryver.setQuery(HISTORY_CLUSTER_VER, parameters);
		#endif /* HAVE_EXT_POSTGRESQL */
    }
    else if (is_dash_arg_prefix(argv[i],"debug",1)) {
          // dprintf to console
          dprintf_set_tool_debug("TOOL", 0);
    }
    else if (is_dash_arg_prefix(argv[i],"diagnostic",4)) {
          // dprintf to console
          diagnostic = true;
    }
    else if (is_dash_arg_prefix(argv[i], "name", 1)) {
        i++;
        if (argc <= i)
        {
            fprintf(stderr,
                "Error: Argument -name requires name of a remote schedd\n");
            fprintf(stderr,
                "\t\te.g. condor_history -name submit.example.com \n");
            exit(1);
        }
        g_name = argv[i];
        readfromfile = false;
       #ifdef HAVE_EXT_POSTGRESQL
        remoteread = true;
       #endif
    }
    else if (is_dash_arg_prefix(argv[i], "pool", 1)) {
        i++;    
        if (argc <= i)
        {
            fprintf(stderr,
                "Error: Argument -name requires name of a remote schedd\n");
            fprintf(stderr,
                "\t\te.g. condor_history -name submit.example.com \n");
            exit(1);    
        }       
        g_pool = argv[i];
        readfromfile = false;
       #ifdef HAVE_EXT_POSTGRESQL
        remoteread = true;
       #endif
    }
    else {
		std::string ownerconst;
		owner = argv[i];
		formatstr(ownerconst, "%s == \"%s\"", ATTR_OWNER, owner);
		constraint.addCustomOR(ownerconst.c_str());
#ifdef HAVE_EXT_POSTGRESQL
		parameters[0] = owner;
		queryhor.setQuery(HISTORY_OWNER_HOR, parameters);
		queryver.setQuery(HISTORY_OWNER_VER, parameters);<commit_msg>reject unrecognised arguments with error message and usage in condor_history #5706 ===VersionHistory:Pending===<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_config.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_attributes.h"
#include "condor_distribution.h"
#include "dc_collector.h"
#include "dc_schedd.h"
#include "get_daemon_name.h"
#include "internet.h"
#include "print_wrapped_text.h"
#include "MyString.h"
#include "metric_units.h"
#include "ad_printmask.h"
#include "directory.h"
#include "iso_dates.h"
#include "basename.h" // for condor_dirname
#include "match_prefix.h"
#include "subsystem_info.h"
#include "historyFileFinder.h"
#include "condor_id.h"
#include "userlog_to_classads.h"

#include "history_utils.h"
#include "backward_file_reader.h"
#include <fcntl.h>  // for O_BINARY

#ifdef HAVE_EXT_POSTGRESQL
#include "sqlquery.h"
#include "historysnapshot.h"
#define NUM_PARAMETERS 3
#endif /* HAVE_EXT_POSTGRESQL */

static int getConsoleWindowSize(int * pHeight = NULL);
void Usage(char* name, int iExitCode=1);

void Usage(char* name, int iExitCode) 
{
	printf ("Usage: %s [source] [restriction-list] [options]\n"
		"\n   where [source] is one of\n"
		"\t-file <file>\t\tRead history data from specified file\n"
		"\t-userlog <file>\t\tRead job data specified userlog file\n"
		"\t-name <schedd-name>\tRemote schedd to read from\n"
		"\t-pool <collector-name>\tPool remote schedd lives in.\n"
		"   If neither -pool, -name, -userlog or -file is specified, then the local history file is used.\n"
#ifdef HAVE_EXT_POSTGRESQL
		"\t-dbname <schedd-name>\tRead history data from Quill database\n"
		"\t-completedsince <time>\tDisplay jobs completed on/after time\n"
#endif
		"\n   and [restriction-list] is one or more of\n"
		"\t<cluster>\t\tGet information about specific cluster\n"
		"\t<cluster>.<proc>\tGet information about specific job\n"
		"\t<owner>\t\t\tInformation about jobs owned by <owner>\n"
		"\t-constraint <expr>\tInformation about jobs matching <expr>\n"
		"\n   and [options] are one or more of\n"
		"\t-help\t\t\tDisplay this screen\n"
		"\t-backwards\t\tList jobs in reverse chronological order\n"
		"\t-forwards\t\tList jobs in chronological order\n"
		"\t-limit <number>\t\tLimit the number of jobs displayed\n"
		"\t-match <number>\t\tOld name for -limit\n"
		"\t-long\t\t\tDisplay entire classads\n"
		"\t-wide[:<width>]\tcon\tDon't truncate fields to fit into 80 columns\n"
		"\t-format <fmt> <attr>\tDisplay attr using printf formatting\n"
		"\t-autoformat[:lhVr,tng] <attr> [<attr2 ...]   Display attr(s) with automatic formatting\n"
		"\t-af[:lhVr,tng] <attr> [<attr2 ...]\t    Same as -autoformat above\n"
		"\t    where the [lhVr,tng] options influence the automatic formatting:\n"
		"\t    l\tattribute labels\n"
		"\t    h\tattribute column headings\n"
		"\t    V\t%%V formatting (string values are quoted)\n"
		"\t    r\t%%r formatting (raw/unparsed values)\n"
		"\t    t\ttab before each value (default is space)\n"
		"\t    g\tnewline between ClassAds, no space before values\n"
		"\t    ,\tcomma after each value\n"
		"\t    n\tnewline after each value\n"
		"\t    use -af:h to get tabular values with headings\n"
		"\t-print-format <file>\tUse <file> to specify the attributes and formatting\n"
		"\t\t\t\t(experimental, see htcondor-wiki for more information)\n"
		, name);
  exit(iExitCode);
}

#ifdef HAVE_EXT_POSTGRESQL
static char * getDBConnStr(char *&quillName, char *&databaseIp, char *&databaseName, char *&queryPassword);
static bool checkDBconfig();
static	QueryResult result;
#endif /* HAVE_EXT_POSTGRESQL */

static void readHistoryRemote(classad::ExprTree *constraintExpr);
static void readHistoryFromFiles(bool fileisuserlog, const char *JobHistoryFileName, const char* constraint, ExprTree *constraintExpr);
static void readHistoryFromFileOld(const char *JobHistoryFileName, const char* constraint, ExprTree *constraintExpr);
static void readHistoryFromFileEx(const char *JobHistoryFileName, const char* constraint, ExprTree *constraintExpr, bool read_backwards);
static void printJobAds(ClassAdList & jobs);
static void printJob(ClassAd & ad);

static int set_print_mask_from_stream(AttrListPrintMask & print_mask, std::string & constraint, const char * streamid, bool is_filename);
static int getDisplayWidth();


//------------------------------------------------------------------------

static CollectorList * Collectors = NULL;
#ifdef HAVE_EXT_POSTGRESQL
static	CondorQuery	quillQuery(QUILL_AD);
static	ClassAdList	quillList;
#endif
static  bool longformat=false;
static  bool diagnostic = false;
static  bool use_xml=false;
static  bool wide_format=false;
static  int  wide_format_width = 0;
static  bool customFormat=false;
static  bool disable_user_print_files=false;
static  bool backwards=true;
static  AttrListPrintMask mask;
//tj: headings moved into the mask object.
//static  List<const char> headings; // The list of headings for the mask entries
static int cluster=-1, proc=-1;
static int specifiedMatch = 0, matchCount = 0;
static std::string g_name, g_pool;

int
main(int argc, char* argv[])
{
  Collectors = NULL;

#ifdef HAVE_EXT_POSTGRESQL
  HistorySnapshot *historySnapshot;
  SQLQuery queryhor;
  SQLQuery queryver;
  QuillErrCode st;
  bool remotequill=false;
  char *quillName=NULL;
  AttrList *ad=0;
  int flag = 1;
  void **parameters;
  char *dbconn=NULL;
  char *completedsince = NULL;
  char *dbIpAddr=NULL, *dbName=NULL,*queryPassword=NULL;
  bool remoteread = false;
#endif /* HAVE_EXT_POSTGRESQL */

  const char *owner=NULL;
  bool readfromfile = true;
  bool fileisuserlog = false;

  char* JobHistoryFileName=NULL;
  const char * pcolon=NULL;


  GenericQuery constraint; // used to build a complex constraint.
  ExprTree *constraintExpr=NULL;

  std::string tmp;

  int i;
  myDistro->Init( argc, argv );

  config();

#ifdef HAVE_EXT_POSTGRESQL
  parameters = (void **) malloc(NUM_PARAMETERS * sizeof(void *));
  queryhor.setQuery(HISTORY_ALL_HOR, NULL);
  queryver.setQuery(HISTORY_ALL_VER, NULL);
#endif /* HAVE_EXT_POSTGRESQL */

  for(i=1; i<argc; i++) {
    if (is_dash_arg_prefix(argv[i],"long",1)) {
      longformat=TRUE;   
    }
    
    else if (is_dash_arg_prefix(argv[i],"xml",3)) {
		use_xml = true;	
		longformat = true;
	}
    
    else if (is_dash_arg_prefix(argv[i],"backwards",1)) {
        backwards=TRUE;
    }

	// must be at least -forw to avoid conflict with -f (for file) and -format
    else if (is_dash_arg_prefix(argv[i],"nobackwards",3) ||
			 is_dash_arg_prefix(argv[i],"forwards",4)) {
        backwards=FALSE;
    }

    else if (is_dash_arg_colon_prefix(argv[i],"wide", &pcolon, 1)) {
        wide_format=TRUE;
        if (pcolon) {
            wide_format_width = atoi(++pcolon);
            if ( ! mask.IsEmpty()) mask.SetOverallWidth(getDisplayWidth()-1);
            if (wide_format_width <= 80) wide_format = FALSE;
        }
    }

    else if (is_dash_arg_prefix(argv[i],"match",1) || is_dash_arg_prefix(argv[i],"limit",3)) {
        i++;
        if (argc <= i) {
            fprintf(stderr,
                    "Error: Argument -match requires a number value "
                    " as a parameter.\n");
            exit(1);
        }
        specifiedMatch = atoi(argv[i]);
    }

#ifdef HAVE_EXT_POSTGRESQL
    else if(is_dash_arg_prefix(argv[i], "dbname",1)) {
		i++;
		if (argc <= i) {
			fprintf( stderr,
					 "Error: Argument -dbname requires the name of a quilld as a parameter\n" );
			exit(1);
		}
		

/*
		if( !(quillName = get_daemon_name(argv[i])) ) {
			fprintf( stderr, "Error: unknown host %s\n",
					 get_host_part(argv[i]) );
			printf("\n");
			print_wrapped_text("Extra Info: The name given with the -dbname "
							   "should be the name of a condor_quilld process. "
							   "Normally it is either a hostname, or "
							   "\"name@hostname\". "
							   "In either case, the hostname should be the "
							   "Internet host name, but it appears that it "
							   "wasn't.",
							   stderr);
			exit(1);
		}
		sprintf (tmp, "%s == \"%s\"", ATTR_NAME, quillName);      		
		quillQuery.addORConstraint (tmp);

*/
		quillName = argv[i];

		sprintf (tmp, "%s == \"%s\"", ATTR_SCHEDD_NAME, quillName);
		quillQuery.addORConstraint (tmp.c_str());

		remotequill = false;
		readfromfile = false;
    }
#endif /* HAVE_EXT_POSTGRESQL */
    else if (is_dash_arg_prefix(argv[i],"file",2)) {
		if (i+1==argc || JobHistoryFileName) break;
		i++;
		JobHistoryFileName=argv[i];
		readfromfile = true;
    }
	else if (is_dash_arg_prefix(argv[i],"userlog",1)) {
		if (i+1==argc || JobHistoryFileName) break;
		i++;
		JobHistoryFileName=argv[i];
		readfromfile = true;
		fileisuserlog = true;
	}
    else if (is_dash_arg_prefix(argv[i],"help",1)) {
		Usage(argv[0],0);
    }
    else if (is_dash_arg_prefix(argv[i],"format",1)) {
		if (argc <= i + 2) {
			fprintf(stderr,
					"Error: Argument -format requires a spec and "
					"classad attribute name as parameters.\n");
			fprintf(stderr,
					"\t\te.g. condor_history -format '%%d' ClusterId\n");
			exit(1);
		}
		mask.registerFormat(argv[i + 1], argv[i + 2]);
		customFormat = true;
		i += 2;
    }
	else if (*(argv[i]) == '-' && 
				(is_arg_colon_prefix(argv[i]+1,"af", &pcolon, 2) ||
				 is_arg_colon_prefix(argv[i]+1,"autoformat", &pcolon, 5))) {
		// make sure we have at least one argument to autoformat
		if (argc <= i+1 || *(argv[i+1]) == '-') {
			fprintf (stderr, "Error: Argument %s requires at last one attribute parameter\n", argv[i]);
			fprintf(stderr, "\t\te.g. condor_history %s ClusterId\n", argv[i]);
			exit(1);
		}
		if (pcolon) ++pcolon; // if there are options, skip over the colon to the options.
		int ixNext = parse_autoformat_args(argc, argv, i+1, pcolon, mask, diagnostic);
		if (ixNext > i)
			i = ixNext-1;
		customFormat = true;
	}
	else if (is_dash_arg_colon_prefix(argv[i], "print-format", &pcolon, 2)) {
		if ( (argc <= i+1)  || (*(argv[i+1]) == '-' && (argv[i+1])[1] != 0)) {
			fprintf( stderr, "Error: Argument -print-format requires a filename argument\n");
			exit( 1 );
		}
		// hack allow -pr ! to disable use of user-default print format files.
		if (MATCH == strcmp(argv[i+1], "!")) {
			++i;
			disable_user_print_files = true;
			continue;
		}
		if ( ! wide_format) mask.SetOverallWidth(getDisplayWidth()-1);
		customFormat = true;
		++i;
		std::string where_expr;
		if (set_print_mask_from_stream(mask, where_expr, argv[i], true) < 0) {
			fprintf(stderr, "Error: cannot execute print-format file %s\n", argv[i]);
			exit (1);
		}
		if ( ! where_expr.empty()) {
			constraint.addCustomAND(where_expr.c_str());
		}
	}
    else if (is_dash_arg_prefix(argv[i],"constraint",1)) {
		// make sure we have at least one more argument
		if (argc <= i+1) {
			fprintf( stderr, "Error: Argument %s requires another parameter\n", argv[i]);
			exit(1);
		}
		i++;
		constraint.addCustomAND(argv[i]);
    }
#ifdef HAVE_EXT_POSTGRESQL
    else if (is_dash_arg_prefix(argv[i],"completedsince",3)) {
		i++;
		if (argc <= i) {
			fprintf(stderr,
					"Error: Argument -completedsince requires a date and "
					"optional timestamp as a parameter.\n");
			fprintf(stderr,
					"\t\te.g. condor_history -completedsince \"2004-10-19 10:23:54\"\n");
			exit(1);
		}
		
		if (constraint!="") break;
		completedsince = strdup(argv[i]);
		parameters[0] = completedsince;
		queryhor.setQuery(HISTORY_COMPLETEDSINCE_HOR,parameters);
		queryver.setQuery(HISTORY_COMPLETEDSINCE_VER,parameters);
    }
#endif /* HAVE_EXT_POSTGRESQL */

    else if (sscanf (argv[i], "%d.%d", &cluster, &proc) == 2) {
		std::string jobconst;
		formatstr (jobconst, "%s == %d && %s == %d", 
				 ATTR_CLUSTER_ID, cluster,ATTR_PROC_ID, proc);
		constraint.addCustomOR(jobconst.c_str());
		#ifdef HAVE_EXT_POSTGRESQL
		parameters[0] = &cluster;
		parameters[1] = &proc;
		queryhor.setQuery(HISTORY_CLUSTER_PROC_HOR, parameters);
		queryver.setQuery(HISTORY_CLUSTER_PROC_VER, parameters);
		#endif /* HAVE_EXT_POSTGRESQL */
    }
    else if (sscanf (argv[i], "%d", &cluster) == 1) {
		std::string jobconst;
		formatstr (jobconst, "%s == %d", ATTR_CLUSTER_ID, cluster);
		constraint.addCustomOR(jobconst.c_str());
		#ifdef HAVE_EXT_POSTGRESQL
		parameters[0] = &cluster;
		queryhor.setQuery(HISTORY_CLUSTER_HOR, parameters);
		queryver.setQuery(HISTORY_CLUSTER_VER, parameters);
		#endif /* HAVE_EXT_POSTGRESQL */
    }
    else if (is_dash_arg_prefix(argv[i],"debug",1)) {
          // dprintf to console
          dprintf_set_tool_debug("TOOL", 0);
    }
    else if (is_dash_arg_prefix(argv[i],"diagnostic",4)) {
          // dprintf to console
          diagnostic = true;
    }
    else if (is_dash_arg_prefix(argv[i], "name", 1)) {
        i++;
        if (argc <= i)
        {
            fprintf(stderr,
                "Error: Argument -name requires name of a remote schedd\n");
            fprintf(stderr,
                "\t\te.g. condor_history -name submit.example.com \n");
            exit(1);
        }
        g_name = argv[i];
        readfromfile = false;
       #ifdef HAVE_EXT_POSTGRESQL
        remoteread = true;
       #endif
    }
    else if (is_dash_arg_prefix(argv[i], "pool", 1)) {
        i++;    
        if (argc <= i)
        {
            fprintf(stderr,
                "Error: Argument -name requires name of a remote schedd\n");
            fprintf(stderr,
                "\t\te.g. condor_history -name submit.example.com \n");
            exit(1);    
        }       
        g_pool = argv[i];
        readfromfile = false;
       #ifdef HAVE_EXT_POSTGRESQL
        remoteread = true;
       #endif
    }
	else if (argv[i][0] == '-') {
		fprintf(stderr, "Error: Unknown argument %s\n", argv[i]);
		break; // quitting now will print usage and exit with an error below.
	}
	else {
		std::string ownerconst;
		owner = argv[i];
		formatstr(ownerconst, "%s == \"%s\"", ATTR_OWNER, owner);
		constraint.addCustomOR(ownerconst.c_str());
#ifdef HAVE_EXT_POSTGRESQL
		parameters[0] = owner;
		queryhor.setQuery(HISTORY_OWNER_HOR, parameters);
		queryver.setQuery(HISTORY_OWNER_VER, parameters);
{'fraction_non_alphanumeric': 0.150194816195155, 'fraction_numerical': 0.007419955954599356, 'mean_word_length': 3.4734768111548955, 'pattern_counts': {'":': 0, '<': 79, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6247434', 'n_tokens_mistral': 10925, 'n_tokens_neox': 10219, 'n_words': 2571}