2005-04-10 16:30:47 +01:00
|
|
|
/**
|
|
|
|
*@file switches.c
|
|
|
|
* \brief Handle command-line options
|
|
|
|
*
|
|
|
|
* Contains the main switch handling.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "string.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "version.h"
|
|
|
|
#include "timer.h"
|
2005-06-07 16:02:27 +01:00
|
|
|
#include "switches.h"
|
2005-06-16 15:10:07 +01:00
|
|
|
#include "specialterm.h"
|
2005-06-07 16:02:27 +01:00
|
|
|
#include <limits.h>
|
2005-04-10 16:30:47 +01:00
|
|
|
|
2005-06-07 16:02:27 +01:00
|
|
|
struct switchdata switches;
|
2005-04-10 16:30:47 +01:00
|
|
|
|
|
|
|
extern struct tacnode *spdltac;
|
|
|
|
|
|
|
|
const char *progname = "scyther";
|
|
|
|
const char *releasetag = SVNVERSION;
|
|
|
|
|
2005-06-07 16:02:27 +01:00
|
|
|
// Forward declarations
|
|
|
|
void process_switches ();
|
|
|
|
|
|
|
|
//! Init switches
|
|
|
|
/**
|
|
|
|
* Set them all to the default settings.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
switchesInit (int argc, char **argv)
|
|
|
|
{
|
|
|
|
// Command-line
|
|
|
|
switches.argc = argc;
|
|
|
|
switches.argv = argv;
|
|
|
|
|
|
|
|
// Methods
|
2005-11-04 13:23:30 +00:00
|
|
|
switches.engine = ARACHNE_ENGINE; // default is arachne engine
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.match = 0; // default matching
|
|
|
|
switches.clp = 0;
|
2005-08-12 13:59:25 +01:00
|
|
|
switches.tupling = 0;
|
2005-06-07 16:02:27 +01:00
|
|
|
|
|
|
|
// Pruning and Bounding
|
|
|
|
switches.prune = 2; // default pruning method
|
|
|
|
switches.maxproofdepth = INT_MAX;
|
|
|
|
switches.maxtracelength = INT_MAX;
|
2005-11-12 21:26:50 +00:00
|
|
|
switches.runs = 6; // default is 6 for usability, but -r 0 or --maxruns=0 will set it back to INT_MAX
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.filterClaim = NULL; // default check all claims
|
2005-08-15 13:49:32 +01:00
|
|
|
switches.maxAttacks = 0; // no maximum default
|
2005-06-07 16:02:27 +01:00
|
|
|
|
|
|
|
// Modelchecker
|
|
|
|
switches.traverse = 12; // default traversal method
|
|
|
|
switches.forceChoose = 1; // force explicit chooses by default
|
|
|
|
switches.chooseFirst = 0; // no priority to chooses by default
|
|
|
|
switches.readSymmetries = 0; // don't force read symmetries by default
|
|
|
|
switches.agentSymmetries = 1; // default enable agent symmetry
|
|
|
|
switches.orderSymmetries = 0; // don't force symmetry order reduction by default
|
|
|
|
switches.pruneNomoreClaims = 1; // default cutter when there are no more claims
|
|
|
|
switches.reduceEndgame = 1; // default cutter of last events in a trace
|
|
|
|
switches.reduceClaims = 1; // default remove claims from duplicate instance choosers
|
|
|
|
// Parallellism
|
|
|
|
switches.scenario = 0;
|
|
|
|
switches.scenarioSize = 0;
|
|
|
|
|
|
|
|
// Arachne
|
|
|
|
switches.arachneSelector = 3; // default goal selection method
|
2005-08-21 22:38:32 +01:00
|
|
|
switches.maxIntruderActions = INT_MAX; // max number of encrypt/decrypt events
|
2005-10-08 20:54:30 +01:00
|
|
|
switches.agentTypecheck = 1; // default do check agent types
|
2005-11-12 21:26:50 +00:00
|
|
|
switches.concrete = true; // default removes symbols, and makes traces concrete
|
2005-11-29 09:15:16 +00:00
|
|
|
switches.extravert = false; // default allows also initiator Alice to talk to Alice
|
2005-12-21 19:02:41 +00:00
|
|
|
switches.intruder = true; // default allows an intruder
|
2005-06-07 16:02:27 +01:00
|
|
|
|
|
|
|
// Misc
|
|
|
|
switches.switchP = 0; // multi-purpose parameter
|
2005-10-07 14:09:07 +01:00
|
|
|
switches.experimental = 0; // experimental stuff defaults to 0, whatever that means.
|
2005-06-07 16:02:27 +01:00
|
|
|
|
|
|
|
// Output
|
|
|
|
switches.output = ATTACK; // default is to show the attacks
|
|
|
|
switches.report = 0;
|
|
|
|
switches.reportClaims = 0; // default don't report on claims
|
|
|
|
switches.xml = 0; // default no xml output
|
|
|
|
switches.human = false; // not human friendly by default
|
2005-06-21 12:04:34 +01:00
|
|
|
switches.reportMemory = 0;
|
|
|
|
switches.reportTime = 0;
|
|
|
|
switches.reportStates = 0;
|
|
|
|
switches.extendNonReads = 0; // default off
|
2005-08-12 13:13:50 +01:00
|
|
|
switches.extendTrivial = 0; // default off
|
2005-06-21 12:04:34 +01:00
|
|
|
|
2005-06-07 16:02:27 +01:00
|
|
|
// Obsolete
|
|
|
|
switches.latex = 0; // latex output?
|
|
|
|
|
|
|
|
process_switches ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Exit
|
|
|
|
void
|
|
|
|
switchesDone (void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2005-04-10 16:30:47 +01:00
|
|
|
//! Process a single switch or generate help text
|
|
|
|
/**
|
|
|
|
* When process is false, we just generate the help text.
|
|
|
|
*
|
|
|
|
* Yields new index, or -1 when an error occurred.
|
|
|
|
* When the new index > argc, it should not be called anymore.
|
|
|
|
* By convention, argc = the number of arguments + 1
|
|
|
|
* The index steps through 1..argc-1.
|
|
|
|
*/
|
|
|
|
int
|
2005-06-07 16:02:27 +01:00
|
|
|
switcher (const int process, int index)
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
char *this_arg; // just a shortcut
|
2005-04-15 15:31:32 +01:00
|
|
|
int this_arg_length; // same here
|
|
|
|
|
2005-04-10 16:30:47 +01:00
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
|
|
|
|
char *arg_pointer;
|
|
|
|
int arg_index;
|
|
|
|
|
|
|
|
//! Check whether there are still n options left
|
|
|
|
int enough_arguments_left (const int n, char shortopt, char *longopt)
|
|
|
|
{
|
|
|
|
if (index + n > argc)
|
|
|
|
{
|
|
|
|
error ("Option %c [%s] needs at least %i arguments.", shortopt,
|
|
|
|
longopt, n);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip over (processed) argument
|
|
|
|
void arg_next (void)
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
arg_pointer = argv[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Parse an argument into an integer
|
|
|
|
int integer_argument (void)
|
|
|
|
{
|
|
|
|
int result;
|
|
|
|
|
|
|
|
if (arg_pointer == NULL)
|
|
|
|
{
|
|
|
|
error ("(Integer) argument expected.");
|
|
|
|
}
|
|
|
|
result = 0;
|
|
|
|
if (sscanf (arg_pointer, "%i", &result) != 1)
|
|
|
|
{
|
|
|
|
error ("Could not parse expected integer argument.");
|
|
|
|
}
|
|
|
|
arg_next ();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Detect whether this confirms to this option.
|
|
|
|
/**
|
|
|
|
* set arg_pointer and index
|
|
|
|
*/
|
|
|
|
int detect (char shortopt, char *longopt, int args)
|
|
|
|
{
|
|
|
|
arg_pointer = NULL;
|
|
|
|
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
// If we are not processing, we always yield true.
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
// Is it this option anyway?
|
2005-04-15 15:31:32 +01:00
|
|
|
if (this_arg_length < 2 || this_arg[0] != '-')
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
// No option
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// Compare
|
|
|
|
if (this_arg[1] == '-')
|
|
|
|
{
|
|
|
|
int optlength;
|
|
|
|
|
2005-04-15 15:31:32 +01:00
|
|
|
// This seems to be a long switch, so we handle it accordingly
|
|
|
|
|
2005-04-10 16:30:47 +01:00
|
|
|
optlength = strlen (longopt);
|
|
|
|
if (strncmp (this_arg + 2, longopt, optlength))
|
|
|
|
return 0;
|
2005-04-15 15:31:32 +01:00
|
|
|
if (optlength + 2 < this_arg_length)
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
// This has an additional thing!
|
2005-04-15 15:31:32 +01:00
|
|
|
if (args > 0 && this_arg[2 + optlength] == '=')
|
|
|
|
{
|
|
|
|
// It's the right thing
|
|
|
|
if (optlength + 3 < this_arg_length)
|
|
|
|
{
|
2005-05-01 14:32:50 +01:00
|
|
|
arg_pointer = this_arg + 2 + optlength + 1;
|
2005-04-15 15:31:32 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// arg = next
|
|
|
|
index++;
|
|
|
|
arg_pointer = argv[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// It's not this option
|
|
|
|
return 0;
|
|
|
|
}
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// arg = next
|
|
|
|
index++;
|
|
|
|
arg_pointer = argv[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Short variant
|
2005-04-15 15:31:32 +01:00
|
|
|
if (this_arg_length < 2 || this_arg[1] != shortopt)
|
2005-04-10 16:30:47 +01:00
|
|
|
return 0;
|
2005-04-15 15:31:32 +01:00
|
|
|
if (args > 0 && this_arg_length > 2)
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
// This has an additional thing!
|
2005-04-15 15:31:32 +01:00
|
|
|
// We assume the argument follows immediately (no appended '=')
|
2005-04-10 16:30:47 +01:00
|
|
|
arg_pointer = this_arg + 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// arg = next
|
|
|
|
index++;
|
|
|
|
arg_pointer = argv[index];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Allright, this is the right option
|
|
|
|
// Enough arguments left?
|
|
|
|
return enough_arguments_left (args, shortopt, longopt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Align columns
|
|
|
|
void helptext (const char *left, const char *right)
|
|
|
|
{
|
|
|
|
printf (" %-25s %s\n", left, right);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process)
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
argc = switches.argc;
|
|
|
|
argv = switches.argv;
|
2005-04-10 16:30:47 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
// Check range for debug; we trust the non-debug version :)
|
|
|
|
if (index < 1 || index >= argc)
|
|
|
|
{
|
|
|
|
error ("Bad index number %i for argc %i", index, argc);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
this_arg = argv[index];
|
2005-05-01 14:32:50 +01:00
|
|
|
this_arg_length = strlen (this_arg);
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Just doing help
|
|
|
|
this_arg = NULL;
|
2005-04-15 15:31:32 +01:00
|
|
|
this_arg_length = 0;
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* -------------------------------------------------------------
|
|
|
|
* Process the options, one by one
|
|
|
|
* -------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
/* ==================
|
|
|
|
* Generic options
|
|
|
|
*/
|
|
|
|
if (detect ('a', "arachne", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-11-04 13:23:30 +00:00
|
|
|
/*
|
|
|
|
* Obsolete switch, as it is now the default behaviour.
|
|
|
|
*/
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
// Select arachne engine
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.engine = ARACHNE_ENGINE;
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-04 13:23:30 +00:00
|
|
|
if (detect ('M', "modelchecker", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-11-12 21:13:00 +00:00
|
|
|
helptext ("-M,--modelchecker",
|
|
|
|
"select Model checking engine [Arachne]");
|
2005-11-04 13:23:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Select arachne engine
|
|
|
|
switches.engine = POR_ENGINE;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-01 14:32:50 +01:00
|
|
|
if (detect ('x', "xml-output", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
helptext ("-x,--xml-output", "show attack output in XML format");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.xml = 1;
|
2005-05-01 14:32:50 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('m', "match", 1))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-11-12 21:13:00 +00:00
|
|
|
helptext ("-m,--match=<int>",
|
|
|
|
"matching method [0] (0:Typed,1:Basic,2:Typeless)");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.match = integer_argument ();
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('T', "timer", 1))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
/* Not shown in from help, as we don't want to encourage this
|
|
|
|
helptext ("-T,--timer=<int>", "maximum time in seconds [inf]");
|
|
|
|
*/
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
set_time_limit (integer_argument ());
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('r', "max-runs", 1))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
helptext ("-r,--max-runs=<int>",
|
2005-11-12 21:26:50 +00:00
|
|
|
"maximum number of runs in the system [6]. Set to 0 for unbounded search.");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-11-12 21:26:50 +00:00
|
|
|
int arg = integer_argument ();
|
|
|
|
if (arg == 0)
|
|
|
|
{
|
|
|
|
switches.runs = INT_MAX;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.runs = arg;
|
|
|
|
}
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('l', "max-length", 1))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
helptext ("-l,--max-length=<int>",
|
|
|
|
"prune traces longer than <int> events [inf]");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.maxtracelength = integer_argument ();
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-15 13:49:32 +01:00
|
|
|
if (detect (' ', "max-attacks", 1))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* not very important
|
|
|
|
helptext ("--max-attacks=<int>", "when not 0, maximum number of attacks [0]");
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.maxAttacks = integer_argument ();
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('p', "prune", 1))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
/* not very important
|
|
|
|
helptext ("-p,--prune=<int>", "pruning method when an attack is found [0]");
|
|
|
|
*/
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.prune = integer_argument ();
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-06-02 09:25:45 +01:00
|
|
|
if (detect ('H', "human-readable", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
helptext ("-H,--human-readable",
|
2005-11-12 21:26:50 +00:00
|
|
|
"try to make the output human-friendly (e.g. in XML).");
|
2005-06-02 09:25:45 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.human = true;
|
2005-11-12 21:13:00 +00:00
|
|
|
switches.concrete = true;
|
2005-06-02 09:25:45 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-12 13:59:25 +01:00
|
|
|
if (detect (' ', "ra-tupling", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* for experts only
|
|
|
|
helptext ("--ra-tupling", "compile using right-associative tupling");
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.tupling = 0;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-12 08:28:44 +01:00
|
|
|
if (detect (' ', "la-tupling", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-08-12 13:59:25 +01:00
|
|
|
/* for experts only
|
2005-08-12 08:28:44 +01:00
|
|
|
helptext ("--la-tupling", "compile using left-associative tupling");
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-08-12 13:59:25 +01:00
|
|
|
switches.tupling = 1;
|
2005-08-12 08:28:44 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-12 13:59:25 +01:00
|
|
|
if (detect (' ', "tupling", 1))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* for experts only
|
|
|
|
helptext ("--tupling", "tupling type to use");
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.tupling = integer_argument ();
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
/* ==================
|
|
|
|
* Modelchecker only
|
|
|
|
*/
|
|
|
|
if (!process)
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
printf ("Switches for modelchecking engine:\n");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('L', "latex", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
helptext ("-L,--latex", "output attacks in LaTeX format [ASCII]");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.latex = 1;
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect (' ', "state-space", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
helptext ("--state-space",
|
|
|
|
"output state space graph (in DOT format)");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.output = STATESPACE;
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
/* ==================
|
|
|
|
* Arachne only
|
|
|
|
*/
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
printf ("Switches for Arachne engine:\n");
|
|
|
|
helptext ("(fixed)", "output attacks in DOT format");
|
|
|
|
}
|
|
|
|
|
2005-04-10 16:30:47 +01:00
|
|
|
if (detect ('G', "goal-select", 1))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
/* discourage: hide
|
|
|
|
helptext ("-G,--goal-select=<int>",
|
|
|
|
"use goal selection method <int> [3]");
|
|
|
|
*/
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.arachneSelector = integer_argument ();
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('P', "proof", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
helptext ("-P,--proof", "show explicit proof");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
// Proof
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.output = PROOF;
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-06-21 12:04:34 +01:00
|
|
|
if (detect (' ', "extend-nonreads", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* discourage: hide
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.extendNonReads = 1;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-12-21 19:02:41 +00:00
|
|
|
if (detect (' ', "no-intruder", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* for testing purposes: hide
|
|
|
|
*
|
|
|
|
* Disables the intruder
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.intruder = false;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-29 09:15:16 +00:00
|
|
|
if (detect (' ', "extravert", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* discourage: hide
|
|
|
|
*
|
|
|
|
* Finds only attacks which exclude initiator Alice talking to Alice
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.extravert = true;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-12 13:13:50 +01:00
|
|
|
if (detect (' ', "extend-trivial", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* discourage: hide
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.extendTrivial = 1;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-21 22:38:32 +01:00
|
|
|
if (detect (' ', "intruder-actions", 1))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* fairly technical, untested pruning */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.maxIntruderActions = integer_argument ();
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-08 20:54:30 +01:00
|
|
|
if (detect (' ', "disable-agenttypecheck", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* maybe add after testing */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.agentTypecheck = 0;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-12 21:26:50 +00:00
|
|
|
if (detect ('C', "class", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
helptext ("-C,--class",
|
|
|
|
"generate full class (show uninstantiated variables)");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.concrete = false;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-12 21:13:00 +00:00
|
|
|
if (detect (' ', "concrete", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-11-12 21:26:50 +00:00
|
|
|
/* this is now the default */
|
2005-11-12 21:13:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.concrete = true;
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-07 14:09:07 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
/* ==================
|
|
|
|
* Experimental options
|
|
|
|
*
|
|
|
|
* Only with debugging version
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (detect (' ', "experimental", 1))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
/* unpredictable behaviour, can change throughout versions */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switches.experimental = integer_argument ();
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
/* ==================
|
|
|
|
* External options
|
|
|
|
*/
|
|
|
|
if (!process)
|
|
|
|
printf ("Misc. switches:\n");
|
|
|
|
|
|
|
|
if (detect ('E', "echo", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
/* not very important
|
|
|
|
helptext ("-E,--echo", "echo command line");
|
|
|
|
*/
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
/* print command line */
|
|
|
|
fprintf (stdout, "command\t");
|
2005-06-07 16:02:27 +01:00
|
|
|
commandlinePrint (stdout);
|
2005-04-15 11:04:05 +01:00
|
|
|
fprintf (stdout, "\n");
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-04 13:23:30 +00:00
|
|
|
if (detect ('S', "summary", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-11-04 13:23:30 +00:00
|
|
|
helptext ("-S,--summary", "show summary only: omit attack details");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.output = SUMMARY;
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('b', "progress-bar", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
/* discourage: do not show in help text
|
|
|
|
helptext ("-b,--progress-bar", "show progress bar");
|
|
|
|
*/
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.reportStates = 50000;
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('e', "empty", 0))
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
/* not very important
|
|
|
|
helptext ("-e,--empty", "do not generate output");
|
|
|
|
*/
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
switches.output = EMPTY;
|
2005-04-10 16:30:47 +01:00
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (detect ('v', "version", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
2005-04-15 11:04:05 +01:00
|
|
|
{
|
|
|
|
/* not very important: hide
|
|
|
|
helptext ("-v,--version", "version information");
|
|
|
|
*/
|
|
|
|
}
|
2005-04-10 16:30:47 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
printf ("'%s' model checker for security protocols.\n", progname);
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf ("Revision %s, compiled with debugging support.\n",
|
|
|
|
SVNVERSION);
|
|
|
|
#else
|
|
|
|
printf ("Revision %s\n", SVNVERSION);
|
|
|
|
#endif
|
2005-04-15 15:31:32 +01:00
|
|
|
printf ("Code by Cas Cremers\n");
|
2005-04-10 16:30:47 +01:00
|
|
|
exit (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (detect ('h', "help", 0))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
helptext ("-h,--help", "show this help");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf ("Usage:\n");
|
|
|
|
printf (" %s [switches] [FILE]\nSwitches:\n", progname);
|
2005-06-07 16:02:27 +01:00
|
|
|
switcher (0, 0);
|
2005-04-10 16:30:47 +01:00
|
|
|
exit (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (detect ('D', "debug", 1))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 11:04:05 +01:00
|
|
|
helptext ("-D,--debug=<int>", "set debug (verbosity) level. [0]");
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debugSet (integer_argument ());
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-15 11:04:05 +01:00
|
|
|
if (detect ('o', "output", 1))
|
|
|
|
{
|
|
|
|
if (!process)
|
|
|
|
{
|
2005-04-15 15:33:18 +01:00
|
|
|
helptext ("-o,--output=<FILE>", "output file [stdout]");
|
2005-04-15 11:04:05 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Set output file name
|
|
|
|
/* try to open */
|
|
|
|
if (!freopen (arg_pointer, "w", stdout))
|
|
|
|
{
|
|
|
|
fprintf (stderr, "Could not create output file '%s'.\n",
|
|
|
|
arg_pointer);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
arg_next ();
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-10 16:30:47 +01:00
|
|
|
// If the option is not recognized, it means a file name.
|
|
|
|
if (!process)
|
|
|
|
{
|
|
|
|
helptext ("FILE", "input file ('-' for stdin)");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!strcmp (this_arg, "-"))
|
|
|
|
{
|
|
|
|
// '-' input: Leave input to stdin
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not '-' input: change stdin to come from this file
|
|
|
|
if (!freopen (this_arg, "r", stdin))
|
|
|
|
{
|
2005-04-15 15:31:32 +01:00
|
|
|
// The file was not found. We have two options...
|
|
|
|
if (this_arg[0] == '-')
|
|
|
|
{
|
|
|
|
fprintf (stderr, "Unknown switch '%s'.\n", this_arg);
|
|
|
|
}
|
2005-05-01 14:32:50 +01:00
|
|
|
else
|
2005-04-15 15:31:32 +01:00
|
|
|
{
|
2005-05-01 14:32:50 +01:00
|
|
|
fprintf (stderr, "Could not open input file '%s'.\n",
|
|
|
|
this_arg);
|
2005-04-15 15:31:32 +01:00
|
|
|
}
|
2005-04-10 16:30:47 +01:00
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
return index + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Process switches
|
|
|
|
void
|
2005-06-07 16:02:27 +01:00
|
|
|
process_switches ()
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
|
|
|
int index;
|
|
|
|
|
2005-06-07 16:02:27 +01:00
|
|
|
if (switches.argc == 1)
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
2005-04-15 15:31:32 +01:00
|
|
|
printf ("Try '%s --help' for more information, or visit:\n", progname);
|
|
|
|
printf (" http://www.win.tue.nl/~ccremers/scyther/index.html\n");
|
2005-04-10 16:30:47 +01:00
|
|
|
exit (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
index = 1;
|
2005-06-07 16:02:27 +01:00
|
|
|
while (index < switches.argc && index > 0)
|
2005-04-10 16:30:47 +01:00
|
|
|
{
|
2005-06-07 16:02:27 +01:00
|
|
|
index = switcher (1, index);
|
2005-04-10 16:30:47 +01:00
|
|
|
}
|
|
|
|
}
|