diff --git a/README.md b/README.md index ef60985..1443ab1 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,7 @@ -# ShiftOS -[![Discord](https://discordapp.com/api/guilds/234414439330349056/widget.png?style=shield)](https://discord.gg/RJbcybn) -[![Build status](https://ci.appveyor.com/api/projects/status/ktdv3nt6c3q88g2t?svg=true)](https://ci.appveyor.com/project/ComputeLinux/shiftos) +# This project is deprecated. -The official, open-source, C# revamp of ShiftOS. +ShiftOS, as of July 30th, 2017, has officially been marked as deprecated by the project leader. We may bring it back in the future as we believe the concept is unique and awesome, but we are not sure when or if. -## License +If you have any questions or concerns, you may contact the project leader at michaelshiftos@gmail.com. -We are licensed under the [MIT license](https://github.com/shiftos-game/ShiftOS/blob/master/LICENSE). A simple description is: - -1. Don't steal our code and claim ownership of it -2. Leave copyright statements and license info at the top of all .cs files. `InsertLicense.exe` can be used to add the license to all files without it. - - -### Using our code for your own project - -You may use the ShiftOS.Engine, ShiftOS.Objects, and ShiftOS.Server projects to create your own games. You must include the original license and link back to [ShiftOS](https://github.com/shiftos-game/ShiftOS) in your `README` and in your game or credits. - -## Compiling the code - -To compile the ShiftOS project, first, make sure you have Visual Studio Community installed (recommended version: 2015). Then, install **MonoGame 3.6** from [here](http://www.monogame.net/downloads/). After installing these dependencies, open up **`ShiftOS_TheReturn.sln`** in Visual Studio. - -Then, set the `ShiftOS.Frontend` project as your startup project, by right-clicking it in Solution Explorer and clicking "Set As StartUp Project". Then, fucking smash that F5 key and watch as ShiftOS comes to life. - -## Where the hell is the **Issues** tab? This can't be GitHub! - -No, you're wrong. We've actually disabled the Issues tab in place of our own in-place [bugtracker](http://getshiftos.ml/Bugs). Please post bugs there. It is easier for us to track and integrate with the rest of the community. - -## Contributing - -See [`CONTRIBUTING.md`](https://github.com/shiftos-game/ShiftOS/blob/master/CONTRIBUTING.md) - -## `Mushroom` - -`I'm a mushroom.` +We apologize to any actual fans of the project. diff --git a/ShiftOS.Frontend/Apps/Terminal.cs b/ShiftOS.Frontend/Apps/Terminal.cs index 343bb5d..4af1196 100644 --- a/ShiftOS.Frontend/Apps/Terminal.cs +++ b/ShiftOS.Frontend/Apps/Terminal.cs @@ -164,34 +164,37 @@ namespace ShiftOS.Frontend.Apps /// An absolute fucking mess. Seriously, can someone fix this method so it uhh WORKS PROPERLY? public System.Drawing.Point GetPointAtIndex(Graphics gfx) { - int vertMeasure = 2; + var font = new Font(LoadedSkin.TerminalFont.Name, LoadedSkin.TerminalFont.Size * _zoomFactor, LoadedSkin.TerminalFont.Style); + + int _textHeight = (int)gfx.SmartMeasureString("#", font).Height; + float vertMeasure = 2; int horizMeasure = 2; if (string.IsNullOrEmpty(Text)) - return new System.Drawing.Point(horizMeasure, vertMeasure); + return new System.Drawing.Point(horizMeasure, (int)vertMeasure); int lineindex = 0; int line = GetCurrentLine(); for (int l = 0; l < line; l++) { - if (string.IsNullOrEmpty(Lines[l])) + lineindex += Lines[l].Length; + if (string.IsNullOrWhiteSpace(Lines[l])) { - vertMeasure += LoadedSkin.TerminalFont.Height * _zoomFactor; + vertMeasure += _textHeight; continue; } - lineindex += Lines[l].Length; - var stringMeasure = gfx.SmartMeasureString(Lines[l] == "\r" ? " " : Lines[l], LoadedSkin.TerminalFont, Width - 4); - vertMeasure += (int)stringMeasure.Height * _zoomFactor; - + var stringMeasure = gfx.SmartMeasureString(Lines[l], font, Width - 4); + vertMeasure += (int)(stringMeasure.Height); + } - var lnMeasure = gfx.SmartMeasureString(Text.Substring(lineindex, Index - lineindex), LoadedSkin.TerminalFont); - int w = (int)Math.Floor(lnMeasure.Width) * _zoomFactor; + var lnMeasure = gfx.SmartMeasureString(Text.Substring(lineindex, Index - lineindex), font); + int w = (int)Math.Floor(lnMeasure.Width); while (w > Width - 4) { w = w - (Width - 4); - vertMeasure += (int)lnMeasure.Height * _zoomFactor; + vertMeasure += (int)lnMeasure.Height; } horizMeasure += w; - return new System.Drawing.Point(horizMeasure, vertMeasure); + return new System.Drawing.Point(horizMeasure, (int)vertMeasure); } private PointF CaretPosition = new PointF(2, 2); @@ -199,7 +202,7 @@ namespace ShiftOS.Frontend.Apps protected override void OnKeyEvent(KeyEvent a) { - if(a.ControlDown && (a.Key == Keys.OemPlus || a.Key == Keys.Add)) + if (a.ControlDown && (a.Key == Keys.OemPlus || a.Key == Keys.Add)) { _zoomFactor *= 2; RecalculateLayout(); @@ -209,7 +212,7 @@ namespace ShiftOS.Frontend.Apps if (a.ControlDown && (a.Key == Keys.OemMinus || a.Key == Keys.Subtract)) { - _zoomFactor = Math.Max(1, _zoomFactor/2); + _zoomFactor = Math.Max(1, _zoomFactor / 2); RecalculateLayout(); Invalidate(); return; @@ -221,7 +224,7 @@ namespace ShiftOS.Frontend.Apps if (!PerformTerminalBehaviours) { Text = Text.Insert(Index, Environment.NewLine); - Index+=2; + Index += 2; RecalculateLayout(); Invalidate(); return; @@ -239,12 +242,12 @@ namespace ShiftOS.Frontend.Apps var text2 = text[text.Length - 1]; var text3 = ""; var text4 = Regex.Replace(text2, @"\t|\n|\r", ""); - WriteLine(""); + WriteLine(""); - if (TerminalBackend.PrefixEnabled) - { - text3 = text4.Remove(0, $"{SaveSystem.CurrentSave.Username}@{SaveSystem.CurrentSave.SystemName}:~$ ".Length); - } + if (TerminalBackend.PrefixEnabled) + { + text3 = text4.Remove(0, TerminalBackend.ShellOverride.Length); + } if (!string.IsNullOrWhiteSpace(text3)) { TerminalBackend.LastCommand = text3; @@ -288,7 +291,7 @@ namespace ShiftOS.Frontend.Apps { var tostring3 = Lines[Lines.Length - 1]; var tostringlen = tostring3.Length + 1; - var workaround = $"{SaveSystem.CurrentSave.Username}@{SaveSystem.CurrentSave.SystemName}:~$ "; + var workaround = TerminalBackend.ShellOverride; var derp = workaround.Length + 1; if (tostringlen != derp) { @@ -310,9 +313,9 @@ namespace ShiftOS.Frontend.Apps Debug.WriteLine("Drunky alert in terminal."); } } - else if(a.Key == Keys.Right) + else if (a.Key == Keys.Right) { - if(Index < Text.Length) + if (Index < Text.Length) { Index++; AppearanceManager.CurrentPosition++; @@ -326,7 +329,7 @@ namespace ShiftOS.Frontend.Apps { var getstring = Lines[Lines.Length - 1]; var stringlen = getstring.Length + 1; - var header = $"{SaveSystem.CurrentSave.Username}@{SaveSystem.CurrentSave.SystemName}:~$ "; + var header = TerminalBackend.ShellOverride; var headerlen = header.Length + 1; var selstart = Index; var remstrlen = Text.Length - stringlen; @@ -343,7 +346,7 @@ namespace ShiftOS.Frontend.Apps else if (a.Key == Keys.Up && PerformTerminalBehaviours) { var tostring3 = Lines[Lines.Length - 1]; - if (tostring3 == $"{SaveSystem.CurrentSave.Username}@{SaveSystem.CurrentSave.SystemName}:~$ ") + if (tostring3 == TerminalBackend.ShellOverride) Console.Write(TerminalBackend.LastCommand); ConsoleEx.OnFlush?.Invoke(); return; @@ -360,7 +363,7 @@ namespace ShiftOS.Frontend.Apps Text = Text.Insert(Index, a.KeyChar.ToString()); Index++; AppearanceManager.CurrentPosition++; -// RecalculateLayout(); + // RecalculateLayout(); InvalidateTopLevel(); } } diff --git a/ShiftOS.Frontend/Commands.cs b/ShiftOS.Frontend/Commands.cs index 012d0b0..da1d1c1 100644 --- a/ShiftOS.Frontend/Commands.cs +++ b/ShiftOS.Frontend/Commands.cs @@ -47,6 +47,7 @@ namespace ShiftOS.Frontend [TutorialLock] public static class TerminalCommands { + [MetaCommand] [Command("clear", description = "{DESC_CLEAR}")] public static bool Clear() { @@ -60,14 +61,21 @@ namespace ShiftOS.Frontend public static class ShiftOSCommands { +#if DEBUG + [Command("debug")] + public static void EnterDebug() + { + TerminalBackend.SetShellOverride("shiftos_debug> "); + } +#endif - [Command("setsfxenabled", description = "{DESC_SETSFXENABLED}")] - [RequiresArgument("value")] + [Command("setsfxenabled", description = "{DESC_SETSFXENABLED}")] + [RequiresArgument("id")] public static bool SetSfxEnabled(Dictionary args) { try { - bool value = Convert.ToBoolean(args["value"].ToString()); + bool value = Convert.ToBoolean(args["id"].ToString()); SaveSystem.CurrentSave.SoundEnabled = value; SaveSystem.SaveGame(); } @@ -81,12 +89,12 @@ namespace ShiftOS.Frontend [Command("setmusicenabled", description = "{DESC_SETMUSICENABLED}")] - [RequiresArgument("value")] + [RequiresArgument("id")] public static bool SetMusicEnabled(Dictionary args) { try { - bool value = Convert.ToBoolean(args["value"].ToString()); + bool value = Convert.ToBoolean(args["id"].ToString()); SaveSystem.CurrentSave.MusicEnabled = value; SaveSystem.SaveGame(); } @@ -100,10 +108,10 @@ namespace ShiftOS.Frontend [Command("setvolume", description ="{DESC_SETVOLUME}")] - [RequiresArgument("value")] + [RequiresArgument("id")] public static bool SetSfxVolume(Dictionary args) { - int value = int.Parse(args["value"].ToString()); + int value = int.Parse(args["id"].ToString()); if(value >= 0 && value <= 100) { SaveSystem.CurrentSave.MusicVolume = value; @@ -127,14 +135,14 @@ namespace ShiftOS.Frontend } [Command("lang", description = "{DESC_LANG}")] - [RequiresArgument("language")] + [RequiresArgument("id")] public static bool SetLanguage(Dictionary userArgs) { try { string lang = ""; - lang = (string)userArgs["language"]; + lang = (string)userArgs["id"]; if (Localization.GetAllLanguages().Contains(lang)) { @@ -152,7 +160,8 @@ namespace ShiftOS.Frontend } } - [Command("commands", "", "{DESC_COMMANDS}")] + [MetaCommand] + [Command("help", "", "{DESC_COMMANDS}")] public static bool Commands() { var sb = new StringBuilder(); @@ -160,7 +169,7 @@ namespace ShiftOS.Frontend sb.AppendLine("================="); sb.AppendLine(); //print all unique namespaces. - foreach (var n in TerminalBackend.Commands.Where(x => !(x is TerminalBackend.WinOpenCommand) && Shiftorium.UpgradeInstalled(x.Dependencies) && x.CommandInfo.hide == false).OrderBy(x => x.CommandInfo.name)) + foreach (var n in TerminalBackend.Commands.Where(x => !(x is TerminalBackend.WinOpenCommand) && Shiftorium.UpgradeInstalled(x.Dependencies) && x.CommandInfo.hide == false && x.MatchShell() == true).OrderBy(x => x.CommandInfo.name)) { sb.Append(" - " + n.CommandInfo.name); if (!string.IsNullOrWhiteSpace(n.CommandInfo.description)) @@ -174,13 +183,6 @@ namespace ShiftOS.Frontend return true; } - [Command("help", description = "{DESC_HELP}")] - public static bool Help() - { - Commands(); - WindowCommands.Programs(); - return true; - } [MultiplayerOnly] @@ -237,14 +239,14 @@ namespace ShiftOS.Frontend public static class ShiftoriumCommands { [Command("buy", description = "{DESC_BUY}")] - [RequiresArgument("upgrade")] + [RequiresArgument("id")] public static bool BuyUpgrade(Dictionary userArgs) { try { string upgrade = ""; - upgrade = (string)userArgs["upgrade"]; + upgrade = (string)userArgs["id"]; var upg = Shiftorium.GetAvailable().FirstOrDefault(x => x.ID == upgrade); if(upg != null) @@ -267,12 +269,12 @@ namespace ShiftOS.Frontend [RequiresUpgrade("shiftorium_bulk_buy")] [Command("bulkbuy", description = "{DESC_BULKBUY}")] - [RequiresArgument("upgrades")] + [RequiresArgument("id")] public static bool BuyBulk(Dictionary args) { - if (args.ContainsKey("upgrades")) + if (args.ContainsKey("id")) { - string[] upgrade_list = (args["upgrades"] as string).Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); + string[] upgrade_list = (args["id"] as string).Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); foreach (var upg in upgrade_list) { var dict = new Dictionary(); @@ -285,14 +287,14 @@ namespace ShiftOS.Frontend [Command("upgradeinfo", description ="{DESC_UPGRADEINFO}")] - [RequiresArgument("upgrade")] + [RequiresArgument("id")] public static bool ViewInfo(Dictionary userArgs) { try { string upgrade = ""; - upgrade = (string)userArgs["upgrade"]; + upgrade = (string)userArgs["id"]; foreach (var upg in Shiftorium.GetDefaults()) { @@ -447,14 +449,13 @@ namespace ShiftOS.Frontend } [RemoteLock] - [Command("close", usage = "{win:integer32}", description ="{DESC_CLOSE}")] - [RequiresArgument("win")] - [RequiresUpgrade("close_command")] + [Command("close", description ="{DESC_CLOSE}")] + [RequiresArgument("id")] public static bool CloseWindow(Dictionary args) { int winNum = -1; - if (args.ContainsKey("win")) - winNum = Convert.ToInt32(args["win"].ToString()); + if (args.ContainsKey("id")) + winNum = Convert.ToInt32(args["id"].ToString()); string err = null; if (winNum < 0 || winNum >= AppearanceManager.OpenForms.Count) diff --git a/ShiftOS.Frontend/Hacking/HackerTestCommands.cs b/ShiftOS.Frontend/Hacking/HackerTestCommands.cs index 1b6a1c1..72c648e 100644 --- a/ShiftOS.Frontend/Hacking/HackerTestCommands.cs +++ b/ShiftOS.Frontend/Hacking/HackerTestCommands.cs @@ -10,6 +10,7 @@ namespace ShiftOS.Frontend { public static class HackerTestCommands { + [ShellConstraint("shiftos_debug> ")] [Command("lsports")] public static void ListAllPorts() { @@ -19,6 +20,7 @@ namespace ShiftOS.Frontend } } + [ShellConstraint("shiftos_debug> ")] [Command("describehackable")] [RequiresArgument("id")] public static void DescribeHackable(Dictionary args) @@ -41,6 +43,7 @@ namespace ShiftOS.Frontend Console.WriteLine(hackable.WelcomeMessage); } + [ShellConstraint("shiftos_debug> ")] [Command("describeport")] [RequiresArgument("id")] public static void DescribePort(Dictionary args) diff --git a/ShiftOS.Frontend/Hacking/HackingCommands.cs b/ShiftOS.Frontend/Hacking/HackingCommands.cs index d07b174..9ebb824 100644 --- a/ShiftOS.Frontend/Hacking/HackingCommands.cs +++ b/ShiftOS.Frontend/Hacking/HackingCommands.cs @@ -9,8 +9,21 @@ namespace ShiftOS.Frontend { class HackingCommands { + [Command("sploitset")] + public static void SploitSetEnter(Dictionary args) + { + TerminalBackend.SetShellOverride("sploitset> "); + } + + [Command("ftp")] + public static void FTPEnter(Dictionary args) + { + TerminalBackend.SetShellOverride("SimplFTP> "); + } + //TODO: Implement firewall cracking [Command("connect")] + [MetaCommand] [RequiresArgument("id")] public static void Connect(Dictionary args) { @@ -25,6 +38,7 @@ namespace ShiftOS.Frontend } [Command("exploit")] + [ShellConstraint("sploitset> ")] [RequiresArgument("id")] [RequiresArgument("port")] public static void Exploit(Dictionary args) @@ -32,6 +46,7 @@ namespace ShiftOS.Frontend if (Hacking.CurrentHackable == null) { Console.WriteLine("[connectlib] not connected"); + return; } string Port = args["port"].ToString(); string ExploitName = args["id"].ToString(); @@ -58,12 +73,14 @@ namespace ShiftOS.Frontend } [Command("inject")] + [ShellConstraint("sploitset> ")] [RequiresArgument("id")] public static void InjectPayload(Dictionary args) { if (Hacking.CurrentHackable == null) { Console.WriteLine("[connectlib] not connected"); + return; } string PayloadName = args["id"].ToString(); var PayloadID = Hacking.AvailablePayloads.FirstOrDefault(x => x.ID == PayloadName); @@ -83,11 +100,13 @@ namespace ShiftOS.Frontend } [Command("listports")] + [ShellConstraint("sploitset> ")] public static void ListPorts(Dictionary args) { if (Hacking.CurrentHackable == null) { Console.WriteLine("[connectlib] not connected"); + return; } foreach (var port in Hacking.CurrentHackable.PortsToUnlock) { @@ -96,6 +115,7 @@ namespace ShiftOS.Frontend } [Command("devicescan")] + [ShellConstraint("sploitset> ")] public static void ScanDevices() { Console.WriteLine("[sploitset] found " + Hacking.AvailableToHack.Length + " devices on the network"); @@ -106,6 +126,7 @@ namespace ShiftOS.Frontend } [Command("exploits")] + [ShellConstraint("sploitset> ")] public static void ScanExploits() { Console.WriteLine("[sploitset] found " + Hacking.AvailableExploits.Length + " exploits installed"); @@ -116,6 +137,7 @@ namespace ShiftOS.Frontend } [Command("payloads")] + [ShellConstraint("sploitset> ")] public static void ListAllPayloads() { Console.WriteLine("[sploitset] found " + Hacking.AvailablePayloads.Length + " payloads"); @@ -126,11 +148,13 @@ namespace ShiftOS.Frontend } [Command("disconnect")] + [MetaCommand] public static void Disconnect(Dictionary args) { if (Hacking.CurrentHackable == null) { Console.WriteLine("[connectlib] not connected"); + return; } if (Hacking.CurrentHackable.PayloadExecuted.Count == 0) { @@ -140,12 +164,20 @@ namespace ShiftOS.Frontend Hacking.FinishHack(); } - [Command("ftp-list")] + [Command("list")] + [ShellConstraint("SimplFTP> ")] public static void ListAllFTP(Dictionary args) { if (Hacking.CurrentHackable == null) { Console.WriteLine("[connectlib] not connected"); + return; + } + var PayloadID = Hacking.CurrentHackable.PayloadExecuted.FirstOrDefault(x => x.EffectiveAgainst.HasFlag(Objects.SystemType.FileServer)); + if (PayloadID == null) + { + Console.WriteLine("[SimplFTP] Not authorised."); + return; } foreach (var loot in Hacking.CurrentHackable.ServerFTPLoot) { @@ -153,13 +185,21 @@ namespace ShiftOS.Frontend } } - [Command("ftp-download")] + [Command("download")] + [ShellConstraint("SimplFTP> ")] [RequiresArgument("file")] public static void DownloadFTP(Dictionary args) { if (Hacking.CurrentHackable == null) { Console.WriteLine("[connectlib] not connected"); + return; + } + var PayloadID = Hacking.CurrentHackable.PayloadExecuted.FirstOrDefault(x => x.EffectiveAgainst.HasFlag(Objects.SystemType.FileServer)); + if (PayloadID == null) + { + Console.WriteLine("[SimplFTP] Not authorised."); + return; } string FindName = args["file"].ToString(); var LootID = Hacking.AvailableLoot.FirstOrDefault(x => x.LootName == FindName); diff --git a/ShiftOS_TheReturn/CommandParser.cs b/ShiftOS_TheReturn/CommandParser.cs index d56e7bd..7568b98 100644 --- a/ShiftOS_TheReturn/CommandParser.cs +++ b/ShiftOS_TheReturn/CommandParser.cs @@ -12,17 +12,6 @@ using System.Windows.Forms; namespace ShiftOS.Engine { - /// - /// Static abstraction layer for the current command parser - /// - public static class CurrentCommandParser - { - /// - /// The current parser - /// - public static CommandParser parser; - } - /// /// Provides functionality for parsing a Terminal command string /// @@ -119,6 +108,8 @@ namespace ShiftOS.Engine int i = 0; string currentArgument = ""; int help = -1; + bool id_found = false; + string id_text = ""; while (position < text.Length) { @@ -131,7 +122,21 @@ namespace ShiftOS.Engine } CommandFormat part = parts[i]; - string res = part.CheckValidity(text.Substring(position)); + string inp = text.Substring(position); + string res = part.CheckValidity(inp); + if(part is CommandFormatText) + { + if(res == "+FALSE+") + { + if(id_found == false) + { + id_found = true; + id_text = inp.Remove(0,1); + res = ""; + arguments.Add("id", id_text); + } + } + } // ok so: @@ -148,8 +153,17 @@ namespace ShiftOS.Engine } else if (part is CommandFormatArgument) { - currentArgument = res; - help = -1; + if (arguments.ContainsKey(res)) + { + Console.WriteLine("Duplicate command-line argument detected: " + res); + command = "+FALSE+"; + position = text.Length; + } + else + { + currentArgument = res; + help = -1; + } } else if (part is CommandFormatValue) { diff --git a/ShiftOS_TheReturn/Hacking.cs b/ShiftOS_TheReturn/Hacking.cs index b9149d9..8412203 100644 --- a/ShiftOS_TheReturn/Hacking.cs +++ b/ShiftOS_TheReturn/Hacking.cs @@ -111,7 +111,7 @@ namespace ShiftOS.Engine var amount = data.LootAmount; for (int i = 0; i < amount; i++) { - int idx = rnd.Next(0, loot.Count - 1); + int idx = rnd.Next(0, loot.Count); //warning MV1224: Random.Next(min, max) - max is not inclusive, i.e the number will always be less than it and equal to or greater than min. hsys.ServerFTPLoot.Add(loot[idx]); loot.RemoveAt(idx); } @@ -124,10 +124,13 @@ namespace ShiftOS.Engine throw new NaughtyDeveloperException("Someone tried to fail a non-existent hack."); if (CurrentHackable.IsPwn3d) throw new NaughtyDeveloperException("A developer tried to un-pwn a pwn3d hackable."); + Console.WriteLine(); Console.WriteLine("[sploitset] [FAIL] disconnected - connection terminated by remote machine "); if (!string.IsNullOrWhiteSpace(CurrentHackable.Data.OnHackFailedStoryEvent)) Story.Start(CurrentHackable.Data.OnHackFailedStoryEvent); CurrentHackable = null; + TerminalBackend.SetShellOverride(""); + TerminalBackend.PrintPrompt(); } public static void EndHack() diff --git a/ShiftOS_TheReturn/TerminalBackend.cs b/ShiftOS_TheReturn/TerminalBackend.cs index 689465f..dcc4625 100644 --- a/ShiftOS_TheReturn/TerminalBackend.cs +++ b/ShiftOS_TheReturn/TerminalBackend.cs @@ -40,6 +40,29 @@ namespace ShiftOS.Engine /// public static class TerminalBackend { + private static string _shellOverrideString = ""; + + + /// + /// Gets the current shell prompt override string. + /// + public static string ShellOverride + { + get + { + return (string.IsNullOrWhiteSpace(_shellOverrideString) || SaveSystem.CurrentSave == null) ? $"{SaveSystem.CurrentSave.Username}@{SaveSystem.CurrentSave.SystemName}:~$ " : _shellOverrideString; + } + } + + /// + /// Sets the shell override string to the specified value. Empty string or to use the default ShiftOS string. + /// + /// The string to use as a shell prompt. + public static void SetShellOverride(string value) + { + _shellOverrideString = value; + } + /// /// Occurs when a command is processed. /// @@ -133,6 +156,17 @@ namespace ShiftOS.Engine public class TerminalCommand { + public virtual bool MatchShell() + { + if(ShellMatch != "metacmd") + { + return (ShellMatch == _shellOverrideString); + } + return true; + } + + public string ShellMatch { get; set; } + public override int GetHashCode() { int hash = 0; @@ -178,11 +212,19 @@ namespace ShiftOS.Engine public virtual void Invoke(Dictionary args) { List errors = new List(); + if (ShellMatch != "metacmd") + { + if (ShellMatch != TerminalBackend._shellOverrideString) + { + errors.Add("Command not found."); + } + } + if (errors.Count > 0) { foreach (var error in errors) { - Console.WriteLine("Command error: " + error); + Console.WriteLine(error); } return; } @@ -197,10 +239,28 @@ namespace ShiftOS.Engine } } + [MetaCommand] + [Command("exit")] + public static void Exit() + { + if (_shellOverrideString != "") + _shellOverrideString = ""; + else + { + Console.WriteLine("error: cannot exit system shell"); + } + } + + public class WinOpenCommand : TerminalCommand { public Type ShiftOSWindow { get; set; } + public override bool MatchShell() + { + return (_shellOverrideString == ""); + } + public override void Invoke(Dictionary args) { @@ -296,6 +356,13 @@ namespace ShiftOS.Engine var tc = new TerminalCommand(); tc.RequiresElevation = !(type.GetCustomAttributes(false).FirstOrDefault(x => x is KernelModeAttribute) == null); + var shellConstraint = mth.GetCustomAttributes(false).FirstOrDefault(x => x is ShellConstraintAttribute) as ShellConstraintAttribute; + tc.ShellMatch = (shellConstraint == null) ? "" : shellConstraint.Shell; + + if(mth.GetCustomAttributes(false).FirstOrDefault(x=>x is MetaCommandAttribute) != null) + { + tc.ShellMatch = "metacmd"; + } tc.CommandInfo = cmd as Command; tc.RequiresElevation = tc.RequiresElevation || !(mth.GetCustomAttributes(false).FirstOrDefault(x => x is KernelModeAttribute) == null); @@ -471,42 +538,23 @@ namespace ShiftOS.Engine return true; } +#if DEBUG + [Command("setshell", hide = true)] + [RequiresArgument("id")] + public static void Debug_SetShellOverrideCMD(Dictionary args) + { + SetShellOverride(args["id"].ToString()); + } +#endif + /// /// Prints the user prompt to the terminal. /// public static void PrintPrompt() { - if (SaveSystem.CurrentSave != null) + if (PrefixEnabled) { - ConsoleEx.BackgroundColor = SkinEngine.LoadedSkin.TerminalBackColorCC; - ConsoleEx.Italic = false; - ConsoleEx.Underline = false; - - ConsoleEx.ForegroundColor = ConsoleColor.Magenta; - ConsoleEx.Bold = true; - - Console.Write(SaveSystem.CurrentSave.Username); - ConsoleEx.Bold = false; - ConsoleEx.ForegroundColor = ConsoleColor.Gray; - Console.Write("@"); - ConsoleEx.Italic = true; - ConsoleEx.Bold = true; - ConsoleEx.ForegroundColor = ConsoleColor.Yellow; - Console.Write(SaveSystem.CurrentSave.SystemName); - ConsoleEx.Italic = false; - ConsoleEx.Bold = false; - ConsoleEx.ForegroundColor = ConsoleColor.Gray; - Console.Write(":~"); - Console.ForegroundColor = ConsoleColor.White; - ConsoleEx.Italic = true; - if (KernelWatchdog.InKernelMode == true) - Console.Write("#"); - else - Console.Write("$"); - ConsoleEx.Italic = false; - ConsoleEx.Bold = false; - ConsoleEx.ForegroundColor = SkinEngine.LoadedSkin.TerminalForeColorCC; - Console.Write(" "); + Console.Write(ShellOverride); ConsoleEx.Flush(); } } @@ -536,4 +584,32 @@ namespace ShiftOS.Engine } } + + /// + /// Marks this command so that it can be run in ANY shell. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class MetaCommandAttribute : Attribute + { + + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class ShellConstraintAttribute : Attribute + { + /// + /// Instructs the terminal command interpreter to disallow running of this command unless the user shell override matches up with the value provided here. + /// + /// The required shell string. Null or whitespace to match with the default ShiftOS shell. + public ShellConstraintAttribute(string shell) + { + Shell = shell; + } + + + /// + /// Gets the required shell string for the command. + /// + public string Shell { get; private set; } + } }