public static int RealMain(string[] args) { bool verboseErrors = false; bool verbose = false; try { List <string> cargs = new List <string>(args); var tmpparsed = FilterCollector.ExtractOptions(cargs); var options = tmpparsed.Item1; var filter = tmpparsed.Item2; verboseErrors = Library.Utility.Utility.ParseBoolOption(options, "debug-output"); verbose = Library.Utility.Utility.ParseBoolOption(options, "verbose"); //If we are on Windows, append the bundled "win-tools" programs to the search path //We add it last, to allow the user to override with other versions if (!Library.Utility.Utility.IsClientLinux) { string wintools = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "win-tools"); Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + System.IO.Path.PathSeparator.ToString() + wintools + System.IO.Path.PathSeparator.ToString() + System.IO.Path.Combine(wintools, "gpg") //GPG needs to be in a subfolder for wrapping reasons ); } #if DEBUG if (cargs.Count > 1 && cargs[0].ToLower() == "unittest") { //The unit test is only enabled in DEBUG builds //it works by getting a list of folders, and treats them as //if they have the same data, but on different times //The first folder is used to make a full backup, //and each subsequent folder is used to make an incremental backup //After all backups are made, the files are restored and verified against //the original folders. //The best way to test it, is to use SVN checkouts at different //revisions, as this is how a regular folder would evolve cargs.RemoveAt(0); UnitTest.RunTest(cargs.ToArray(), options); return(0); } #endif if (cargs.Count == 1 && string.Equals(cargs[0], "changelog", StringComparison.InvariantCultureIgnoreCase)) { var path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "changelog.txt"); Console.WriteLine(System.IO.File.ReadAllText(path)); return(0); } foreach (string internaloption in Library.Main.Options.InternalOptions) { if (options.ContainsKey(internaloption)) { Console.WriteLine(Strings.Program.InternalOptionUsedError, internaloption); return(200); } } // Probe for "help" to avoid extra processing bool isHelp = cargs.Count == 0 || (cargs.Count >= 1 && string.Equals(cargs[0], "help", StringComparison.InvariantCultureIgnoreCase)); if (!isHelp && ((options.ContainsKey("parameters-file") && !string.IsNullOrEmpty("parameters-file")) || (options.ContainsKey("parameter-file") && !string.IsNullOrEmpty("parameter-file")) || (options.ContainsKey("parameterfile") && !string.IsNullOrEmpty("parameterfile")))) { string filename; if (options.ContainsKey("parameters-file") && !string.IsNullOrEmpty("parameters-file")) { filename = options["parameters-file"]; options.Remove("parameters-file"); } else { filename = options["parameter-file"]; options.Remove("parameter-file"); } if (!ReadOptionsFromFile(filename, ref filter, cargs, options)) { return(100); } } string command; if (cargs.Count > 0) { command = cargs[0]; cargs.RemoveAt(0); } else { command = "help"; } // Update probe for help isHelp = string.Equals(command, "help", StringComparison.InvariantCultureIgnoreCase); // Skip the env read if the command is help, otherwise we may report weirdness if (!isHelp) { if (!options.ContainsKey("passphrase")) { if (!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("PASSPHRASE"))) { options["passphrase"] = System.Environment.GetEnvironmentVariable("PASSPHRASE"); } } if (!options.ContainsKey("auth-password")) { if (!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("AUTH_PASSWORD"))) { options["auth-password"] = System.Environment.GetEnvironmentVariable("AUTH_PASSWORD"); } } if (!options.ContainsKey("auth-username")) { if (!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("AUTH_USERNAME"))) { options["auth-username"] = System.Environment.GetEnvironmentVariable("AUTH_USERNAME"); } } } var knownCommands = new Dictionary <string, Func <List <string>, Dictionary <string, string>, Library.Utility.IFilter, int> >(StringComparer.InvariantCultureIgnoreCase); knownCommands["help"] = Commands.Help; knownCommands["find"] = Commands.List; knownCommands["list"] = Commands.List; knownCommands["delete"] = Commands.Delete; knownCommands["backup"] = Commands.Backup; knownCommands["restore"] = Commands.Restore; knownCommands["repair"] = Commands.Repair; knownCommands["compact"] = Commands.Compact; knownCommands["create-report"] = Commands.CreateBugReport; knownCommands["compare"] = Commands.ListChanges; knownCommands["test"] = Commands.Test; knownCommands["verify"] = Commands.Test; knownCommands["test-filters"] = Commands.TestFilters; if (!isHelp && verbose) { Console.WriteLine("Input command: {0}", command); Console.WriteLine("Input arguments: "); foreach (var a in cargs) { Console.WriteLine("\t{0}", a); } Console.WriteLine(); Console.WriteLine("Input options: "); foreach (var n in options) { Console.WriteLine("{0}: {1}", n.Key, n.Value); } Console.WriteLine(); } Duplicati.Library.Utility.TempFile.RemoveOldApplicationTempFiles((path, ex) => { if (verbose) { Console.WriteLine(string.Format("Failed to delete temp file: {0}", path)); } }); if (knownCommands.ContainsKey(command)) { return(knownCommands[command](cargs, options, filter)); } else { Commands.PrintInvalidCommand(command, cargs); return(200); } } catch (Exception ex) { while (ex is System.Reflection.TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } if (!(ex is Library.Interface.CancelException)) { if (!string.IsNullOrEmpty(ex.Message)) { Console.Error.WriteLine(); Console.Error.WriteLine(verboseErrors ? ex.ToString() : ex.Message); } } else { Console.Error.WriteLine(Strings.Program.UnhandledException, ex.ToString()); while (ex.InnerException != null) { ex = ex.InnerException; Console.Error.WriteLine(); Console.Error.WriteLine(Strings.Program.UnhandledInnerException, ex.ToString()); } } //Error = 100 return(100); } }