From 6f21d2d66170a1a3c22b1677eec918ba3940f964 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 09:59:20 +0100 Subject: [PATCH 01/42] Update ci.yml --- .github/workflows/ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d38fd3..f7d6268 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,13 +19,13 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 - + - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - + - name: Cache Maven local repository uses: actions/cache@v4 with: @@ -33,16 +33,16 @@ jobs: key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - - - name: Build (Maven) - run: mvn -B -DskipTests=false package - - - name: Run tests - run: mvn test -B - - - name: Upload build artifact (optional) + + - name: Build and Test with Maven + run: mvn -B clean package + # 'package' phase includes: compile โ†’ test โ†’ package + # Tests run automatically unless -DskipTests=true is specified + + - name: Upload build artifact if: success() uses: actions/upload-artifact@v4 with: name: mycmd-build path: target/*.jar + retention-days: 7 # Auto-cleanup after 7 days From 365e4bbbf58b3b2064b0154f0f37a8121988a396 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:02:04 +0100 Subject: [PATCH 02/42] Update build.yml --- .github/workflows/build.yml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b88d4d..fe85102 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,27 +6,45 @@ on: pull_request: branches: [ main ] +permissions: + contents: read + pull-requests: read + jobs: build: name: ๐Ÿ”จ Build and Package runs-on: ubuntu-latest - + steps: - name: ๐Ÿงฉ Checkout source code uses: actions/checkout@v4 - + - name: โ˜• Set up Java uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '21' cache: maven - + + - name: ๐Ÿ”ง Make Maven wrapper executable + run: chmod +x mvnw + - name: ๐Ÿงฐ Build using Maven Wrapper run: ./mvnw -B clean package - + - name: ๐Ÿ“ฆ Upload built JAR artifact + if: success() uses: actions/upload-artifact@v4 with: - name: MyCMD-GUI + name: MyCMD-GUI-${{ github.sha }} path: target/*.jar + retention-days: 30 + + - name: ๐Ÿ“Š Upload test results (if any) + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ github.sha }} + path: target/surefire-reports/ + retention-days: 7 + continue-on-error: true From 066fc4a2c420494184438d9938e0f386cf9cbf09 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:13:49 +0100 Subject: [PATCH 03/42] Update pom.xml --- pom.xml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pom.xml b/pom.xml index 7b4ff9f..4a7bd63 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,7 @@ 17 17 21 + 2.43.0 @@ -55,6 +56,7 @@ + org.apache.maven.plugins maven-shade-plugin @@ -75,6 +77,30 @@ + + + + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + + + + + validate + + check + + + + + + From ce0513db42f3113985b52ecab955a8b76943e842 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 09:14:11 +0000 Subject: [PATCH 04/42] Apply Spotless formatting --- src/main/java/com/mycmd/App.java | 26 +- src/main/java/com/mycmd/Command.java | 13 +- src/main/java/com/mycmd/CommandRegistry.java | 24 +- src/main/java/com/mycmd/ConsoleShell.java | 32 +- src/main/java/com/mycmd/ShellContext.java | 48 +- src/main/java/com/mycmd/ShellEngine.java | 46 +- src/main/java/com/mycmd/StringUtils.java | 25 +- .../java/com/mycmd/commands/AliasCommand.java | 108 +-- .../java/com/mycmd/commands/ArpCommand.java | 83 ++- .../java/com/mycmd/commands/AssocCommand.java | 71 +- .../com/mycmd/commands/AttribCommand.java | 116 ++-- .../java/com/mycmd/commands/CdCommand.java | 74 +-- .../com/mycmd/commands/ChkdskCommand.java | 100 ++- .../com/mycmd/commands/ChoiceCommand.java | 97 ++- .../mycmd/commands/ClearHistoryCommand.java | 26 +- .../java/com/mycmd/commands/ClipCommand.java | 52 +- .../java/com/mycmd/commands/ClsCommand.java | 46 +- .../java/com/mycmd/commands/ColorCommand.java | 106 +-- .../com/mycmd/commands/CompactCommand.java | 96 ++- .../java/com/mycmd/commands/CopyCommand.java | 62 +- .../java/com/mycmd/commands/DateCommand.java | 36 +- .../java/com/mycmd/commands/DelCommand.java | 48 +- .../java/com/mycmd/commands/DirCommand.java | 36 +- .../mycmd/commands/DriverqueryCommand.java | 77 ++- .../java/com/mycmd/commands/EchoCommand.java | 30 +- .../java/com/mycmd/commands/ExitCommand.java | 26 +- .../java/com/mycmd/commands/FcCommand.java | 258 ++++---- .../java/com/mycmd/commands/FindCommand.java | 201 +++--- .../com/mycmd/commands/FindstrCommand.java | 206 +++--- .../com/mycmd/commands/ForfilesCommand.java | 112 ++-- .../com/mycmd/commands/FsutilCommand.java | 91 ++- .../java/com/mycmd/commands/FtypeCommand.java | 71 +- .../com/mycmd/commands/GetmacCommand.java | 95 ++- .../java/com/mycmd/commands/HelpCommand.java | 88 +-- .../com/mycmd/commands/HistoryCommand.java | 40 +- .../com/mycmd/commands/HostnameCommand.java | 38 +- .../commands/InteractiveSearchCommand.java | 253 ++++--- .../java/com/mycmd/commands/IpConfig.java | 50 +- .../java/com/mycmd/commands/LabelCommand.java | 46 +- .../java/com/mycmd/commands/LsCommand.java | 38 +- .../java/com/mycmd/commands/MkdirCommand.java | 44 +- .../java/com/mycmd/commands/MoreCommand.java | 92 +-- .../java/com/mycmd/commands/MoveCommand.java | 36 +- .../java/com/mycmd/commands/MsgCommand.java | 125 ++-- .../java/com/mycmd/commands/NetCommand.java | 116 ++-- .../java/com/mycmd/commands/NetshCommand.java | 95 ++- .../com/mycmd/commands/NetstatCommand.java | 77 ++- .../com/mycmd/commands/NslookupCommand.java | 85 ++- .../java/com/mycmd/commands/PathCommand.java | 62 +- .../java/com/mycmd/commands/PauseCommand.java | 53 +- .../java/com/mycmd/commands/PingCommand.java | 618 +++++++++--------- .../java/com/mycmd/commands/PwdCommand.java | 24 +- .../java/com/mycmd/commands/RemCommand.java | 26 +- .../com/mycmd/commands/RenameCommand.java | 55 +- .../com/mycmd/commands/ReplaceCommand.java | 66 +- .../java/com/mycmd/commands/RmdirCommand.java | 48 +- .../com/mycmd/commands/RobocopyCommand.java | 103 ++- .../java/com/mycmd/commands/RouteCommand.java | 103 ++- .../mycmd/commands/SearchHistoryCommand.java | 195 +++--- .../java/com/mycmd/commands/SetCommand.java | 64 +- .../java/com/mycmd/commands/SfcCommand.java | 95 ++- .../com/mycmd/commands/ShutdownCommand.java | 151 +++-- .../java/com/mycmd/commands/SortCommand.java | 129 ++-- .../java/com/mycmd/commands/StartCommand.java | 96 +-- .../com/mycmd/commands/SysteminfoCommand.java | 106 ++- .../com/mycmd/commands/TaskkillCommand.java | 100 ++- .../com/mycmd/commands/TasklistCommand.java | 101 ++- .../com/mycmd/commands/TelnetCommand.java | 142 ++-- .../java/com/mycmd/commands/TimeCommand.java | 42 +- .../com/mycmd/commands/TimeoutCommand.java | 318 ++++----- .../java/com/mycmd/commands/TitleCommand.java | 32 +- .../java/com/mycmd/commands/TouchCommand.java | 44 +- .../com/mycmd/commands/TracertCommand.java | 93 ++- .../java/com/mycmd/commands/TreeCommand.java | 60 +- .../java/com/mycmd/commands/TypeCommand.java | 54 +- .../com/mycmd/commands/UnaliasCommand.java | 46 +- .../com/mycmd/commands/UptimeCommand.java | 48 +- .../com/mycmd/commands/VerifyCommand.java | 54 +- .../com/mycmd/commands/VersionCommand.java | 24 +- .../java/com/mycmd/commands/VolCommand.java | 82 +-- .../com/mycmd/commands/WhoamiCommand.java | 24 +- .../java/com/mycmd/commands/WmicCommand.java | 93 ++- .../java/com/mycmd/commands/XcopyCommand.java | 107 ++- src/main/java/com/mycmd/gui/MainApp.java | 83 ++- .../com/mycmd/gui/TerminalController.java | 57 +- 85 files changed, 3626 insertions(+), 3733 deletions(-) diff --git a/src/main/java/com/mycmd/App.java b/src/main/java/com/mycmd/App.java index 4608f28..5ed7a41 100644 --- a/src/main/java/com/mycmd/App.java +++ b/src/main/java/com/mycmd/App.java @@ -3,20 +3,18 @@ import com.mycmd.gui.MainApp; import javafx.application.Application; -/** - * Entry point for MyCMD-GUI. - */ +/** Entry point for MyCMD-GUI. */ public class App { - public static void main(String[] args) { - // Security check to prevent CMD access - String launchedFrom = System.getenv("MYCMD_LAUNCHED"); - if (launchedFrom == null || !launchedFrom.equalsIgnoreCase("true")) { - System.out.println("โŒ MyCMD-GUI cannot be run directly from CMD."); - System.out.println("โžก๏ธ Please use the official launcher (MyCMD.bat)."); - return; - } - - // Launch JavaFX GUI - Application.launch(MainApp.class, args); + public static void main(String[] args) { + // Security check to prevent CMD access + String launchedFrom = System.getenv("MYCMD_LAUNCHED"); + if (launchedFrom == null || !launchedFrom.equalsIgnoreCase("true")) { + System.out.println("โŒ MyCMD-GUI cannot be run directly from CMD."); + System.out.println("โžก๏ธ Please use the official launcher (MyCMD.bat)."); + return; } + + // Launch JavaFX GUI + Application.launch(MainApp.class, args); + } } diff --git a/src/main/java/com/mycmd/Command.java b/src/main/java/com/mycmd/Command.java index fac7b07..a971823 100644 --- a/src/main/java/com/mycmd/Command.java +++ b/src/main/java/com/mycmd/Command.java @@ -2,12 +2,11 @@ import java.io.IOException; -/** - * Interfaace for all commands. - * Every command impleements this - */ +/** Interfaace for all commands. Every command impleements this */ public interface Command { - void execute(String[] args, ShellContext context) throws IOException; - String description(); - String usage(); + void execute(String[] args, ShellContext context) throws IOException; + + String description(); + + String usage(); } diff --git a/src/main/java/com/mycmd/CommandRegistry.java b/src/main/java/com/mycmd/CommandRegistry.java index aaf0358..caa211b 100644 --- a/src/main/java/com/mycmd/CommandRegistry.java +++ b/src/main/java/com/mycmd/CommandRegistry.java @@ -3,21 +3,19 @@ import java.util.HashMap; import java.util.Map; -/** - * Registers and retrieves commands by name. - */ +/** Registers and retrieves commands by name. */ public class CommandRegistry { - private final Map commands = new HashMap<>(); + private final Map commands = new HashMap<>(); - public void register(String name, Command cmd) { - commands.put(name.toLowerCase(), cmd); - } + public void register(String name, Command cmd) { + commands.put(name.toLowerCase(), cmd); + } - public Command get(String name) { - return commands.get(name.toLowerCase()); - } + public Command get(String name) { + return commands.get(name.toLowerCase()); + } - public Map getAll() { - return commands; - } + public Map getAll() { + return commands; + } } diff --git a/src/main/java/com/mycmd/ConsoleShell.java b/src/main/java/com/mycmd/ConsoleShell.java index a35f824..3d32b3c 100644 --- a/src/main/java/com/mycmd/ConsoleShell.java +++ b/src/main/java/com/mycmd/ConsoleShell.java @@ -2,26 +2,24 @@ import java.util.Scanner; -/** - * Developer console mode for debugging. - */ +/** Developer console mode for debugging. */ public class ConsoleShell { - public static void main(String[] args) { - CommandRegistry registry = new CommandRegistry(); - ShellContext context = new ShellContext(); - ShellEngine engine = new ShellEngine(registry, context); + public static void main(String[] args) { + CommandRegistry registry = new CommandRegistry(); + ShellContext context = new ShellContext(); + ShellEngine engine = new ShellEngine(registry, context); - Scanner sc = new Scanner(System.in); - System.out.println("MyCMD Developer Console Mode\n(Type 'exit' to quit)"); + Scanner sc = new Scanner(System.in); + System.out.println("MyCMD Developer Console Mode\n(Type 'exit' to quit)"); - while (true) { - System.out.print("> "); - String input = sc.nextLine(); - if (input.equalsIgnoreCase("exit")) break; - engine.execute(input); - } - - sc.close(); + while (true) { + System.out.print("> "); + String input = sc.nextLine(); + if (input.equalsIgnoreCase("exit")) break; + engine.execute(input); } + + sc.close(); + } } diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index 66dd337..8bac1d3 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -4,39 +4,37 @@ import java.util.HashMap; import java.util.Map; - public class ShellContext { - private File currentDir; - private final Map aliases; + private File currentDir; + private final Map aliases; - private Scanner scanner; + private Scanner scanner; - public ShellContext() { - this.currentDir = new File(System.getProperty("user.dir")); - this.aliases = new HashMap<>(); - } + public ShellContext() { + this.currentDir = new File(System.getProperty("user.dir")); + this.aliases = new HashMap<>(); + } - public File getCurrentDir() { - return currentDir; - } + public File getCurrentDir() { + return currentDir; + } - public void setCurrentDir(File dir) { - if (dir != null && dir.exists() && dir.isDirectory()) { - this.currentDir = dir; - } + public void setCurrentDir(File dir) { + if (dir != null && dir.exists() && dir.isDirectory()) { + this.currentDir = dir; } + } - public Map getAliases() { - return aliases; - } + public Map getAliases() { + return aliases; + } - public void addAlias(String name, String command) { - aliases.put(name, command); - } + public void addAlias(String name, String command) { + aliases.put(name, command); + } - public String resolveAlias(String cmd) { - return aliases.getOrDefault(cmd, cmd); - } + public String resolveAlias(String cmd) { + return aliases.getOrDefault(cmd, cmd); + } } - diff --git a/src/main/java/com/mycmd/ShellEngine.java b/src/main/java/com/mycmd/ShellEngine.java index c22e963..acb8e7e 100644 --- a/src/main/java/com/mycmd/ShellEngine.java +++ b/src/main/java/com/mycmd/ShellEngine.java @@ -3,36 +3,34 @@ import java.io.IOException; import java.util.Arrays; -/** - * Central execution engine. - */ +/** Central execution engine. */ public class ShellEngine { - private final CommandRegistry registry; - private final ShellContext context; + private final CommandRegistry registry; + private final ShellContext context; - public ShellEngine(CommandRegistry registry, ShellContext context) { - this.registry = registry; - this.context = context; - } + public ShellEngine(CommandRegistry registry, ShellContext context) { + this.registry = registry; + this.context = context; + } - public void execute(String input) { - if (input == null || input.trim().isEmpty()) return; + public void execute(String input) { + if (input == null || input.trim().isEmpty()) return; - String[] parts = input.trim().split("\\s+"); - String cmdName = context.resolveAlias(parts[0]); - String[] args = Arrays.copyOfRange(parts, 1, parts.length); + String[] parts = input.trim().split("\\s+"); + String cmdName = context.resolveAlias(parts[0]); + String[] args = Arrays.copyOfRange(parts, 1, parts.length); - Command cmd = registry.get(cmdName); - if (cmd == null) { - System.out.println("โŒ Unknown command: " + cmdName); - return; - } + Command cmd = registry.get(cmdName); + if (cmd == null) { + System.out.println("โŒ Unknown command: " + cmdName); + return; + } - try { - cmd.execute(args, context); - } catch (IOException e) { - System.out.println("โš ๏ธ Error executing command: " + e.getMessage()); - } + try { + cmd.execute(args, context); + } catch (IOException e) { + System.out.println("โš ๏ธ Error executing command: " + e.getMessage()); } + } } diff --git a/src/main/java/com/mycmd/StringUtils.java b/src/main/java/com/mycmd/StringUtils.java index f2e8827..fa5aa70 100644 --- a/src/main/java/com/mycmd/StringUtils.java +++ b/src/main/java/com/mycmd/StringUtils.java @@ -1,20 +1,17 @@ package com.mycmd; -/** - * String helper functions for commands. - */ +/** String helper functions for commands. */ public class StringUtils { - public static boolean isEmpty(String s) { - return s == null || s.trim().isEmpty(); - } + public static boolean isEmpty(String s) { + return s == null || s.trim().isEmpty(); + } - public static String join(String[] arr, int start) { - StringBuilder sb = new StringBuilder(); - for (int i = start; i < arr.length; i++) { - if (i > start) sb.append(' '); - sb.append(arr[i]); - } - return sb.toString(); + public static String join(String[] arr, int start) { + StringBuilder sb = new StringBuilder(); + for (int i = start; i < arr.length; i++) { + if (i > start) sb.append(' '); + sb.append(arr[i]); } + return sb.toString(); + } } - diff --git a/src/main/java/com/mycmd/commands/AliasCommand.java b/src/main/java/com/mycmd/commands/AliasCommand.java index c9bf37d..46fe226 100644 --- a/src/main/java/com/mycmd/commands/AliasCommand.java +++ b/src/main/java/com/mycmd/commands/AliasCommand.java @@ -6,63 +6,63 @@ import java.util.Map; public class AliasCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - // no args: list aliases - if (args == null || args.length == 0) { - Map aliases = context.getAliases(); - if (aliases.isEmpty()) { - System.out.println("No aliases defined."); - } else { - aliases.forEach((k, v) -> System.out.println(k + "=" + v)); - } - return; - } - - // single arg of form name=command - if (args.length == 1 && args[0].contains("=")) { - String[] parts = args[0].split("=", 2); - String name = parts[0].trim(); - String cmd = parts[1].trim(); - if (name.isEmpty() || cmd.isEmpty()) { - System.out.println("Invalid alias format. Usage: \n" + usage()); - return; - } - context.addAlias(name, cmd); - System.out.println("Alias added: " + name + "=" + cmd); - return; - } - - // multiple args: first is name, rest form command - if (args.length >= 2) { - String name = args[0]; - StringBuilder sb = new StringBuilder(); - for (int i = 1; i < args.length; i++) { - if (i > 1) sb.append(' '); - sb.append(args[i]); - } - String cmd = sb.toString(); - if (name.trim().isEmpty() || cmd.trim().isEmpty()) { - System.out.println("Invalid alias. Usage: \n" + usage()); - return; - } - context.addAlias(name, cmd); - System.out.println("Alias added: " + name + "=" + cmd); - return; - } - - System.out.println("Invalid usage. Usage: " + usage()); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + // no args: list aliases + if (args == null || args.length == 0) { + Map aliases = context.getAliases(); + if (aliases.isEmpty()) { + System.out.println("No aliases defined."); + } else { + aliases.forEach((k, v) -> System.out.println(k + "=" + v)); + } + return; } - @Override - public String description() { - return "Create or list command aliases."; + // single arg of form name=command + if (args.length == 1 && args[0].contains("=")) { + String[] parts = args[0].split("=", 2); + String name = parts[0].trim(); + String cmd = parts[1].trim(); + if (name.isEmpty() || cmd.isEmpty()) { + System.out.println("Invalid alias format. Usage: \n" + usage()); + return; + } + context.addAlias(name, cmd); + System.out.println("Alias added: " + name + "=" + cmd); + return; } - @Override - public String usage() { - return "alias # list aliases\n" - + "alias name=command # create alias\n" - + "alias name command... # create alias"; + // multiple args: first is name, rest form command + if (args.length >= 2) { + String name = args[0]; + StringBuilder sb = new StringBuilder(); + for (int i = 1; i < args.length; i++) { + if (i > 1) sb.append(' '); + sb.append(args[i]); + } + String cmd = sb.toString(); + if (name.trim().isEmpty() || cmd.trim().isEmpty()) { + System.out.println("Invalid alias. Usage: \n" + usage()); + return; + } + context.addAlias(name, cmd); + System.out.println("Alias added: " + name + "=" + cmd); + return; } + + System.out.println("Invalid usage. Usage: " + usage()); + } + + @Override + public String description() { + return "Create or list command aliases."; + } + + @Override + public String usage() { + return "alias # list aliases\n" + + "alias name=command # create alias\n" + + "alias name command... # create alias"; + } } diff --git a/src/main/java/com/mycmd/commands/ArpCommand.java b/src/main/java/com/mycmd/commands/ArpCommand.java index 124322e..29e0bd7 100644 --- a/src/main/java/com/mycmd/commands/ArpCommand.java +++ b/src/main/java/com/mycmd/commands/ArpCommand.java @@ -13,57 +13,56 @@ */ public class ArpCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - try { - StringBuilder cmdBuilder = new StringBuilder("arp"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + try { + StringBuilder cmdBuilder = new StringBuilder("arp"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - // Default to -a if no args provided - if (args.length == 0) { - cmdBuilder.append(" -a"); - } + // Default to -a if no args provided + if (args.length == 0) { + cmdBuilder.append(" -a"); + } - ProcessBuilder pb = new ProcessBuilder(); - String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb = new ProcessBuilder(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - pb.command("cmd.exe", "/c", cmdBuilder.toString()); - } else { - pb.command("sh", "-c", cmdBuilder.toString()); - } + if (os.contains("win")) { + pb.command("cmd.exe", "/c", cmdBuilder.toString()); + } else { + pb.command("sh", "-c", cmdBuilder.toString()); + } - Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing arp: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing arp: " + e.getMessage()); } + } - @Override - public String description() { - return "Displays and modifies the IP-to-Physical address translation tables."; - } + @Override + public String description() { + return "Displays and modifies the IP-to-Physical address translation tables."; + } - @Override - public String usage() { - return "arp [-a] [-d ip_addr] [-s ip_addr eth_addr]"; - } + @Override + public String usage() { + return "arp [-a] [-d ip_addr] [-s ip_addr eth_addr]"; + } } diff --git a/src/main/java/com/mycmd/commands/AssocCommand.java b/src/main/java/com/mycmd/commands/AssocCommand.java index d33c1da..e2bced4 100644 --- a/src/main/java/com/mycmd/commands/AssocCommand.java +++ b/src/main/java/com/mycmd/commands/AssocCommand.java @@ -13,44 +13,43 @@ */ public class AssocCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); - - if (!os.contains("win")) { - System.out.println("ASSOC is only available on Windows systems."); - return; - } - - try { - StringBuilder cmdBuilder = new StringBuilder("assoc"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } - - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } - - process.waitFor(); - - } catch (Exception e) { - System.out.println("Error executing assoc: " + e.getMessage()); - } - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - @Override - public String description() { - return "Displays or modifies file extension associations."; + if (!os.contains("win")) { + System.out.println("ASSOC is only available on Windows systems."); + return; } - @Override - public String usage() { - return "assoc [.ext[=[fileType]]]"; + try { + StringBuilder cmdBuilder = new StringBuilder("assoc"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } + + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + + process.waitFor(); + + } catch (Exception e) { + System.out.println("Error executing assoc: " + e.getMessage()); } + } + + @Override + public String description() { + return "Displays or modifies file extension associations."; + } + + @Override + public String usage() { + return "assoc [.ext[=[fileType]]]"; + } } diff --git a/src/main/java/com/mycmd/commands/AttribCommand.java b/src/main/java/com/mycmd/commands/AttribCommand.java index b0203dd..abb9d9d 100644 --- a/src/main/java/com/mycmd/commands/AttribCommand.java +++ b/src/main/java/com/mycmd/commands/AttribCommand.java @@ -14,74 +14,72 @@ */ public class AttribCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Displays or changes file attributes."); - System.out.println( - "\nATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] [[drive:][path]filename] [/S [/D]]"); - System.out.println("\n + Sets an attribute"); - System.out.println(" - Clears an attribute"); - System.out.println(" R Read-only file attribute"); - System.out.println(" A Archive file attribute"); - System.out.println(" S System file attribute"); - System.out.println(" H Hidden file attribute"); - System.out.println( - " /S Processes matching files in the current folder and all subfolders"); - System.out.println(" /D Processes folders as well"); - return; - } - - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Displays or changes file attributes."); + System.out.println( + "\nATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] [[drive:][path]filename] [/S [/D]]"); + System.out.println("\n + Sets an attribute"); + System.out.println(" - Clears an attribute"); + System.out.println(" R Read-only file attribute"); + System.out.println(" A Archive file attribute"); + System.out.println(" S System file attribute"); + System.out.println(" H Hidden file attribute"); + System.out.println(" /S Processes matching files in the current folder and all subfolders"); + System.out.println(" /D Processes folders as well"); + return; + } - if (os.contains("win")) { - try { - StringBuilder cmdBuilder = new StringBuilder("attrib"); - for (String arg : args) { - cmdBuilder.append(" \"").append(arg).append("\""); - } + String os = System.getProperty("os.name").toLowerCase(); - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - pb.directory(context.getCurrentDir()); - Process process = pb.start(); + if (os.contains("win")) { + try { + StringBuilder cmdBuilder = new StringBuilder("attrib"); + for (String arg : args) { + cmdBuilder.append(" \"").append(arg).append("\""); + } - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + pb.directory(context.getCurrentDir()); + Process process = pb.start(); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - process.waitFor(); + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - } catch (Exception e) { - System.out.println("Error executing attrib: " + e.getMessage()); - } - } else { - // Unix-like system - use ls -l to show permissions - if (args.length > 0) { - File file = new File(args[args.length - 1]); - if (!file.isAbsolute()) { - file = new File(context.getCurrentDir(), args[args.length - 1]); - } + process.waitFor(); - System.out.println("File: " + file.getName()); - System.out.println("Readable: " + file.canRead()); - System.out.println("Writable: " + file.canWrite()); - System.out.println("Executable: " + file.canExecute()); - System.out.println("Hidden: " + file.isHidden()); - } + } catch (Exception e) { + System.out.println("Error executing attrib: " + e.getMessage()); + } + } else { + // Unix-like system - use ls -l to show permissions + if (args.length > 0) { + File file = new File(args[args.length - 1]); + if (!file.isAbsolute()) { + file = new File(context.getCurrentDir(), args[args.length - 1]); } - } - @Override - public String description() { - return "Displays or changes file attributes."; + System.out.println("File: " + file.getName()); + System.out.println("Readable: " + file.canRead()); + System.out.println("Writable: " + file.canWrite()); + System.out.println("Executable: " + file.canExecute()); + System.out.println("Hidden: " + file.isHidden()); + } } + } - @Override - public String usage() { - return "attrib [+R | -R] [+A | -A] [+S | -S] [+H | -H] filename"; - } + @Override + public String description() { + return "Displays or changes file attributes."; + } + + @Override + public String usage() { + return "attrib [+R | -R] [+A | -A] [+S | -S] [+H | -H] filename"; + } } diff --git a/src/main/java/com/mycmd/commands/CdCommand.java b/src/main/java/com/mycmd/commands/CdCommand.java index 0c81563..2b8ccd1 100644 --- a/src/main/java/com/mycmd/commands/CdCommand.java +++ b/src/main/java/com/mycmd/commands/CdCommand.java @@ -18,47 +18,47 @@ * current working directory stored in ShellContext. */ public class CdCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - // If no argument, print current directory - if (args.length == 0) { - System.out.println(context.getCurrentDir().getAbsolutePath()); - return; - } - - String dir = args[0]; - File newDir; + @Override + public void execute(String[] args, ShellContext context) { + // If no argument, print current directory + if (args.length == 0) { + System.out.println(context.getCurrentDir().getAbsolutePath()); + return; + } - // Handle "cd .." (go to parent directory) - if (dir.equals("..")) { - File parent = context.getCurrentDir().getParentFile(); - if (parent == null) { - System.out.println("Already at the root directory."); - return; - } - newDir = parent; - } else { - newDir = new File(dir); - if (!newDir.isAbsolute()) { - newDir = new File(context.getCurrentDir(), dir); - } - } + String dir = args[0]; + File newDir; - // Change directory if valid - if (newDir.exists() && newDir.isDirectory()) { - context.setCurrentDir(newDir); - } else { - System.out.println("The system cannot find the path specified."); - } + // Handle "cd .." (go to parent directory) + if (dir.equals("..")) { + File parent = context.getCurrentDir().getParentFile(); + if (parent == null) { + System.out.println("Already at the root directory."); + return; + } + newDir = parent; + } else { + newDir = new File(dir); + if (!newDir.isAbsolute()) { + newDir = new File(context.getCurrentDir(), dir); + } } - @Override - public String description() { - return "Change the current working directory or display it."; + // Change directory if valid + if (newDir.exists() && newDir.isDirectory()) { + context.setCurrentDir(newDir); + } else { + System.out.println("The system cannot find the path specified."); } + } - @Override - public String usage() { - return "cd [path]"; - } + @Override + public String description() { + return "Change the current working directory or display it."; + } + + @Override + public String usage() { + return "cd [path]"; + } } diff --git a/src/main/java/com/mycmd/commands/ChkdskCommand.java b/src/main/java/com/mycmd/commands/ChkdskCommand.java index 015d360..6ea6c9d 100644 --- a/src/main/java/com/mycmd/commands/ChkdskCommand.java +++ b/src/main/java/com/mycmd/commands/ChkdskCommand.java @@ -13,67 +13,63 @@ */ public class ChkdskCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("CHKDSK is only available on Windows systems."); - System.out.println("On Unix-like systems, use 'fsck' instead."); - return; - } + if (!os.contains("win")) { + System.out.println("CHKDSK is only available on Windows systems."); + System.out.println("On Unix-like systems, use 'fsck' instead."); + return; + } - if (args.length == 0) { - System.out.println("Checks a disk and displays a status report."); - System.out.println("\nCHKDSK [volume[[path]filename]]] [/F] [/V] [/R] [/X]"); - System.out.println( - "\n volume Specifies the drive letter (followed by a colon)"); - System.out.println(" /F Fixes errors on the disk"); - System.out.println(" /V Displays the full path of every file"); - System.out.println( - " /R Locates bad sectors and recovers readable information"); - System.out.println( - " /X Forces the volume to dismount first if necessary"); - System.out.println("\nNote: Administrator privileges required."); - return; - } + if (args.length == 0) { + System.out.println("Checks a disk and displays a status report."); + System.out.println("\nCHKDSK [volume[[path]filename]]] [/F] [/V] [/R] [/X]"); + System.out.println("\n volume Specifies the drive letter (followed by a colon)"); + System.out.println(" /F Fixes errors on the disk"); + System.out.println(" /V Displays the full path of every file"); + System.out.println(" /R Locates bad sectors and recovers readable information"); + System.out.println(" /X Forces the volume to dismount first if necessary"); + System.out.println("\nNote: Administrator privileges required."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("chkdsk"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + StringBuilder cmdBuilder = new StringBuilder("chkdsk"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing chkdsk: " + e.getMessage()); - System.out.println("Administrator privileges may be required."); - } + } catch (Exception e) { + System.out.println("Error executing chkdsk: " + e.getMessage()); + System.out.println("Administrator privileges may be required."); } + } - @Override - public String description() { - return "Checks a disk and displays a status report."; - } + @Override + public String description() { + return "Checks a disk and displays a status report."; + } - @Override - public String usage() { - return "chkdsk [volume] [/F] [/V] [/R] [/X]"; - } + @Override + public String usage() { + return "chkdsk [volume] [/F] [/V] [/R] [/X]"; + } } diff --git a/src/main/java/com/mycmd/commands/ChoiceCommand.java b/src/main/java/com/mycmd/commands/ChoiceCommand.java index db3c4c2..fd7ff72 100644 --- a/src/main/java/com/mycmd/commands/ChoiceCommand.java +++ b/src/main/java/com/mycmd/commands/ChoiceCommand.java @@ -12,63 +12,62 @@ */ public class ChoiceCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String choices = "YN"; - String message = "Y/N?"; - boolean caseInsensitive = false; - int defaultChoice = 0; + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String choices = "YN"; + String message = "Y/N?"; + boolean caseInsensitive = false; + int defaultChoice = 0; - // Parse arguments - for (int i = 0; i < args.length; i++) { - String arg = args[i].toUpperCase(); + // Parse arguments + for (int i = 0; i < args.length; i++) { + String arg = args[i].toUpperCase(); - if (arg.equals("/C") && i + 1 < args.length) { - choices = args[++i].toUpperCase(); - } else if (arg.equals("/M") && i + 1 < args.length) { - message = args[++i]; - } else if (arg.equals("/CS")) { - caseInsensitive = false; - } else if (arg.equals("/N")) { - // No display of choices - } else if (arg.equals("/D") && i + 1 < args.length) { - char defChar = args[++i].charAt(0); - defaultChoice = choices.indexOf(Character.toUpperCase(defChar)); - } - } + if (arg.equals("/C") && i + 1 < args.length) { + choices = args[++i].toUpperCase(); + } else if (arg.equals("/M") && i + 1 < args.length) { + message = args[++i]; + } else if (arg.equals("/CS")) { + caseInsensitive = false; + } else if (arg.equals("/N")) { + // No display of choices + } else if (arg.equals("/D") && i + 1 < args.length) { + char defChar = args[++i].charAt(0); + defaultChoice = choices.indexOf(Character.toUpperCase(defChar)); + } + } - System.out.print(message + " [" + String.join(",", choices.split("")) + "]? "); + System.out.print(message + " [" + String.join(",", choices.split("")) + "]? "); - Scanner scanner = new Scanner(System.in); - String input = scanner.nextLine().trim(); + Scanner scanner = new Scanner(System.in); + String input = scanner.nextLine().trim(); - if (input.isEmpty() && defaultChoice >= 0) { - System.out.println(choices.charAt(defaultChoice)); - return; - } + if (input.isEmpty() && defaultChoice >= 0) { + System.out.println(choices.charAt(defaultChoice)); + return; + } - if (input.length() > 0) { - char inputChar = - caseInsensitive ? Character.toUpperCase(input.charAt(0)) : input.charAt(0); - int index = choices.indexOf(inputChar); + if (input.length() > 0) { + char inputChar = caseInsensitive ? Character.toUpperCase(input.charAt(0)) : input.charAt(0); + int index = choices.indexOf(inputChar); - if (index >= 0) { - System.out.println(inputChar); - // Set errorlevel (simulated) - System.setProperty("ERRORLEVEL", String.valueOf(index + 1)); - } else { - System.out.println("Invalid choice."); - } - } + if (index >= 0) { + System.out.println(inputChar); + // Set errorlevel (simulated) + System.setProperty("ERRORLEVEL", String.valueOf(index + 1)); + } else { + System.out.println("Invalid choice."); + } } + } - @Override - public String description() { - return "Prompts the user to select from a set of choices."; - } + @Override + public String description() { + return "Prompts the user to select from a set of choices."; + } - @Override - public String usage() { - return "choice [/C choices] [/M text] [/CS] [/N] [/D choice]"; - } + @Override + public String usage() { + return "choice [/C choices] [/M text] [/CS] [/N] [/D choice]"; + } } diff --git a/src/main/java/com/mycmd/commands/ClearHistoryCommand.java b/src/main/java/com/mycmd/commands/ClearHistoryCommand.java index af17746..782823c 100644 --- a/src/main/java/com/mycmd/commands/ClearHistoryCommand.java +++ b/src/main/java/com/mycmd/commands/ClearHistoryCommand.java @@ -15,19 +15,19 @@ * history. The history is cleared immediately and cannot be recovered. */ public class ClearHistoryCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - context.clearHistory(); - System.out.println("Command history cleared."); - } + @Override + public void execute(String[] args, ShellContext context) { + context.clearHistory(); + System.out.println("Command history cleared."); + } - @Override - public String description() { - return "Clear the stored command history."; - } + @Override + public String description() { + return "Clear the stored command history."; + } - @Override - public String usage() { - return "clearhistory"; - } + @Override + public String usage() { + return "clearhistory"; + } } diff --git a/src/main/java/com/mycmd/commands/ClipCommand.java b/src/main/java/com/mycmd/commands/ClipCommand.java index 1669b1e..4745526 100644 --- a/src/main/java/com/mycmd/commands/ClipCommand.java +++ b/src/main/java/com/mycmd/commands/ClipCommand.java @@ -12,34 +12,34 @@ */ public class ClipCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("CLIP command is only available on Windows systems."); - System.out.println("On Unix-like systems, use 'xclip' or 'pbcopy' instead."); - return; - } - - System.out.println("Redirects command output to the Windows clipboard."); - System.out.println("\nUsage:"); - System.out.println( - " DIR | CLIP Places a copy of the DIR output on the clipboard."); - System.out.println( - " CLIP < README.TXT Places a copy of the text in README.TXT on the clipboard."); - System.out.println("\nNote: Direct clipboard manipulation from MyCMD is limited."); - System.out.println( - "Use the actual Windows CLIP command with piping in CMD for full functionality."); + if (!os.contains("win")) { + System.out.println("CLIP command is only available on Windows systems."); + System.out.println("On Unix-like systems, use 'xclip' or 'pbcopy' instead."); + return; } - @Override - public String description() { - return "Copies text to the Windows clipboard."; - } + System.out.println("Redirects command output to the Windows clipboard."); + System.out.println("\nUsage:"); + System.out.println( + " DIR | CLIP Places a copy of the DIR output on the clipboard."); + System.out.println( + " CLIP < README.TXT Places a copy of the text in README.TXT on the clipboard."); + System.out.println("\nNote: Direct clipboard manipulation from MyCMD is limited."); + System.out.println( + "Use the actual Windows CLIP command with piping in CMD for full functionality."); + } - @Override - public String usage() { - return "command | clip"; - } + @Override + public String description() { + return "Copies text to the Windows clipboard."; + } + + @Override + public String usage() { + return "command | clip"; + } } diff --git a/src/main/java/com/mycmd/commands/ClsCommand.java b/src/main/java/com/mycmd/commands/ClsCommand.java index d5148b7..76586b1 100644 --- a/src/main/java/com/mycmd/commands/ClsCommand.java +++ b/src/main/java/com/mycmd/commands/ClsCommand.java @@ -17,30 +17,30 @@ */ public class ClsCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - try { - String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { // For Windows Users - new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor(); - } else { // For other Operation Systems - new ProcessBuilder("clear").inheritIO().start().waitFor(); - } - } catch (InterruptedException e) { // Restore the interrupted status - Thread.currentThread().interrupt(); - System.out.println("Error while clearing the screen: " + e.getMessage()); - } catch (IOException e) { - System.out.println("Error while clearing the screen: " + e.getMessage()); - } + @Override + public void execute(String[] args, ShellContext context) { + try { + String os = System.getProperty("os.name").toLowerCase(); + if (os.contains("win")) { // For Windows Users + new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor(); + } else { // For other Operation Systems + new ProcessBuilder("clear").inheritIO().start().waitFor(); + } + } catch (InterruptedException e) { // Restore the interrupted status + Thread.currentThread().interrupt(); + System.out.println("Error while clearing the screen: " + e.getMessage()); + } catch (IOException e) { + System.out.println("Error while clearing the screen: " + e.getMessage()); } + } - @Override - public String description() { - return "Clear the console screen."; - } + @Override + public String description() { + return "Clear the console screen."; + } - @Override - public String usage() { - return "cls"; - } + @Override + public String usage() { + return "cls"; + } } diff --git a/src/main/java/com/mycmd/commands/ColorCommand.java b/src/main/java/com/mycmd/commands/ColorCommand.java index f18ae9c..f99ff2b 100644 --- a/src/main/java/com/mycmd/commands/ColorCommand.java +++ b/src/main/java/com/mycmd/commands/ColorCommand.java @@ -18,68 +18,68 @@ *

Note: Background and text colors cannot be the same value. */ public class ColorCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length == 1) { - String color = args[0]; + @Override + public void execute(String[] args, ShellContext context) { + if (args.length == 1) { + String color = args[0]; - if (color.length() != 2) { - System.out.println("Usage: " + usage()); - return; - } + if (color.length() != 2) { + System.out.println("Usage: " + usage()); + return; + } - String background = String.valueOf(color.charAt(0)); - String text = String.valueOf(color.charAt(1)); + String background = String.valueOf(color.charAt(0)); + String text = String.valueOf(color.charAt(1)); - if (background.equals(text)) { - return; - } + if (background.equals(text)) { + return; + } - int bgIndex, fgIndex; - try { - bgIndex = Integer.parseInt(background, 16); - fgIndex = Integer.parseInt(text, 16); - } catch (NumberFormatException e) { - System.out.println("Invalid color code. must use two hexadecimal digits."); - System.out.println("Example: color 0A"); - return; - } + int bgIndex, fgIndex; + try { + bgIndex = Integer.parseInt(background, 16); + fgIndex = Integer.parseInt(text, 16); + } catch (NumberFormatException e) { + System.out.println("Invalid color code. must use two hexadecimal digits."); + System.out.println("Example: color 0A"); + return; + } - String[] ansiForeground = { - "30", "34", "32", "36", "31", "35", "33", "37", "90", "94", "92", "96", "91", "95", - "93", "97" - }; - String[] ansiBackground = { - "40", "44", "42", "46", "41", "45", "43", "47", "100", "104", "102", "106", "101", - "105", "103", "107" - }; + String[] ansiForeground = { + "30", "34", "32", "36", "31", "35", "33", "37", "90", "94", "92", "96", "91", "95", "93", + "97" + }; + String[] ansiBackground = { + "40", "44", "42", "46", "41", "45", "43", "47", "100", "104", "102", "106", "101", "105", + "103", "107" + }; - if (bgIndex >= ansiBackground.length || fgIndex >= ansiForeground.length) { - System.out.println("Invalid color code. must use two hexadecimal digits."); - System.out.println("Example: color 0A"); - return; - } + if (bgIndex >= ansiBackground.length || fgIndex >= ansiForeground.length) { + System.out.println("Invalid color code. must use two hexadecimal digits."); + System.out.println("Example: color 0A"); + return; + } - String bg = "\033[" + ansiBackground[bgIndex] + "m"; - String fg = "\033[" + ansiForeground[fgIndex] + "m"; + String bg = "\033[" + ansiBackground[bgIndex] + "m"; + String fg = "\033[" + ansiForeground[fgIndex] + "m"; - System.out.println(bg + fg); - } else { - // set default color - System.out.println("\033[0m"); - } + System.out.println(bg + fg); + } else { + // set default color + System.out.println("\033[0m"); } + } - @Override - public String description() { - return "Change console text and background colors."; - } + @Override + public String description() { + return "Change console text and background colors."; + } - @Override - public String usage() { - return "color []\n" - + " and are hexadecimal digits (0-9, A-F).\n" - + " Example: color 0A sets black background with bright green text.\n" - + " Call without arguments to reset to default colors."; - } + @Override + public String usage() { + return "color []\n" + + " and are hexadecimal digits (0-9, A-F).\n" + + " Example: color 0A sets black background with bright green text.\n" + + " Call without arguments to reset to default colors."; + } } diff --git a/src/main/java/com/mycmd/commands/CompactCommand.java b/src/main/java/com/mycmd/commands/CompactCommand.java index aafad08..159e635 100644 --- a/src/main/java/com/mycmd/commands/CompactCommand.java +++ b/src/main/java/com/mycmd/commands/CompactCommand.java @@ -14,65 +14,61 @@ */ public class CompactCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("COMPACT is only available on Windows NTFS systems."); - return; - } + if (!os.contains("win")) { + System.out.println("COMPACT is only available on Windows NTFS systems."); + return; + } - if (args.length == 0) { - System.out.println("Displays or alters the compression of files on NTFS partitions."); - System.out.println( - "\nCOMPACT [/C | /U] [/S[:dir]] [/A] [/I] [/F] [/Q] [filename [...]]"); - System.out.println("\n /C Compresses the specified files."); - System.out.println(" /U Uncompresses the specified files."); - System.out.println( - " /S Performs the specified operation on files in the given"); - System.out.println(" directory and all subdirectories."); - System.out.println(" /A Displays files with the hidden or system attributes."); - System.out.println( - " /I Continues performing the specified operation even after"); - System.out.println(" errors have occurred."); - System.out.println(" /F Forces the compress operation on all specified files."); - System.out.println(" /Q Reports only the most essential information."); - return; - } + if (args.length == 0) { + System.out.println("Displays or alters the compression of files on NTFS partitions."); + System.out.println("\nCOMPACT [/C | /U] [/S[:dir]] [/A] [/I] [/F] [/Q] [filename [...]]"); + System.out.println("\n /C Compresses the specified files."); + System.out.println(" /U Uncompresses the specified files."); + System.out.println(" /S Performs the specified operation on files in the given"); + System.out.println(" directory and all subdirectories."); + System.out.println(" /A Displays files with the hidden or system attributes."); + System.out.println(" /I Continues performing the specified operation even after"); + System.out.println(" errors have occurred."); + System.out.println(" /F Forces the compress operation on all specified files."); + System.out.println(" /Q Reports only the most essential information."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("compact"); - for (String arg : args) { - cmdBuilder.append(" \"").append(arg).append("\""); - } + try { + StringBuilder cmdBuilder = new StringBuilder("compact"); + for (String arg : args) { + cmdBuilder.append(" \"").append(arg).append("\""); + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - pb.directory(context.getCurrentDir()); - Process process = pb.start(); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + pb.directory(context.getCurrentDir()); + Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing compact: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing compact: " + e.getMessage()); } + } - @Override - public String description() { - return "Displays or alters the compression of files on NTFS partitions."; - } + @Override + public String description() { + return "Displays or alters the compression of files on NTFS partitions."; + } - @Override - public String usage() { - return "compact [/C | /U] [filename]"; - } + @Override + public String usage() { + return "compact [/C | /U] [filename]"; + } } diff --git a/src/main/java/com/mycmd/commands/CopyCommand.java b/src/main/java/com/mycmd/commands/CopyCommand.java index ba01c40..93d8889 100644 --- a/src/main/java/com/mycmd/commands/CopyCommand.java +++ b/src/main/java/com/mycmd/commands/CopyCommand.java @@ -17,38 +17,38 @@ * operation. If the destination file already exists, it will be overwritten. */ public class CopyCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length < 2) { - System.out.println("Usage: " + usage()); - return; - } - File src = new File(context.getCurrentDir(), args[0]); - File dest = new File(context.getCurrentDir(), args[1]); - if (!src.exists() || !src.isFile()) { - System.out.println("Source file does not exist."); - return; - } - try (InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dest)) { - byte[] buf = new byte[8192]; - int len; - while ((len = in.read(buf)) != -1) { - out.write(buf, 0, len); - } - System.out.println("File copied."); - } catch (IOException e) { - System.out.println("Error copying file: " + e.getMessage()); - } + @Override + public void execute(String[] args, ShellContext context) { + if (args.length < 2) { + System.out.println("Usage: " + usage()); + return; } - - @Override - public String description() { - return "Copy a file from source to destination."; + File src = new File(context.getCurrentDir(), args[0]); + File dest = new File(context.getCurrentDir(), args[1]); + if (!src.exists() || !src.isFile()) { + System.out.println("Source file does not exist."); + return; } - - @Override - public String usage() { - return "copy "; + try (InputStream in = new FileInputStream(src); + OutputStream out = new FileOutputStream(dest)) { + byte[] buf = new byte[8192]; + int len; + while ((len = in.read(buf)) != -1) { + out.write(buf, 0, len); + } + System.out.println("File copied."); + } catch (IOException e) { + System.out.println("Error copying file: " + e.getMessage()); } + } + + @Override + public String description() { + return "Copy a file from source to destination."; + } + + @Override + public String usage() { + return "copy "; + } } diff --git a/src/main/java/com/mycmd/commands/DateCommand.java b/src/main/java/com/mycmd/commands/DateCommand.java index ea60bba..42b0df4 100644 --- a/src/main/java/com/mycmd/commands/DateCommand.java +++ b/src/main/java/com/mycmd/commands/DateCommand.java @@ -12,24 +12,24 @@ * in ISO-8601 format (yyyy-MM-dd). */ public class DateCommand implements Command { - /** - * Print the current date. - * - * @param args ignored for this command; may be empty or contain unused tokens. - * @param context the current shell context; not used by this command. - */ - @Override - public void execute(String[] args, ShellContext context) { - System.out.println("The current date is: " + java.time.LocalDate.now()); - } + /** + * Print the current date. + * + * @param args ignored for this command; may be empty or contain unused tokens. + * @param context the current shell context; not used by this command. + */ + @Override + public void execute(String[] args, ShellContext context) { + System.out.println("The current date is: " + java.time.LocalDate.now()); + } - @Override - public String description() { - return "Display current date."; - } + @Override + public String description() { + return "Display current date."; + } - @Override - public String usage() { - return "date"; - } + @Override + public String usage() { + return "date"; + } } diff --git a/src/main/java/com/mycmd/commands/DelCommand.java b/src/main/java/com/mycmd/commands/DelCommand.java index d2c37bb..144c822 100644 --- a/src/main/java/com/mycmd/commands/DelCommand.java +++ b/src/main/java/com/mycmd/commands/DelCommand.java @@ -16,31 +16,31 @@ *

Note: This command only deletes files, not directories. Use rmdir for directory removal. */ public class DelCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length == 0) { - System.out.println("Usage: " + usage()); - return; - } - for (String name : args) { - File file = new File(context.getCurrentDir(), name); - if (!file.exists() || !file.isFile()) { - System.out.println("File not found: " + name); - } else if (file.delete()) { - System.out.println("Deleted: " + name); - } else { - System.out.println("Failed to delete: " + name); - } - } + @Override + public void execute(String[] args, ShellContext context) { + if (args.length == 0) { + System.out.println("Usage: " + usage()); + return; } - - @Override - public String description() { - return "Delete one or more files."; + for (String name : args) { + File file = new File(context.getCurrentDir(), name); + if (!file.exists() || !file.isFile()) { + System.out.println("File not found: " + name); + } else if (file.delete()) { + System.out.println("Deleted: " + name); + } else { + System.out.println("Failed to delete: " + name); + } } + } - @Override - public String usage() { - return "del [file2 ...]"; - } + @Override + public String description() { + return "Delete one or more files."; + } + + @Override + public String usage() { + return "del [file2 ...]"; + } } diff --git a/src/main/java/com/mycmd/commands/DirCommand.java b/src/main/java/com/mycmd/commands/DirCommand.java index bb57fa8..68d4ab9 100644 --- a/src/main/java/com/mycmd/commands/DirCommand.java +++ b/src/main/java/com/mycmd/commands/DirCommand.java @@ -19,25 +19,25 @@ *

If the directory is empty or cannot be read, an appropriate message is displayed. */ public class DirCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - File[] files = context.getCurrentDir().listFiles(); - if (files == null || files.length == 0) { - System.out.println("No files found."); - return; - } - for (File f : files) { - System.out.println((f.isDirectory() ? "

" : " ") + f.getName()); - } + @Override + public void execute(String[] args, ShellContext context) { + File[] files = context.getCurrentDir().listFiles(); + if (files == null || files.length == 0) { + System.out.println("No files found."); + return; } - - @Override - public String description() { - return "Display the contents of working directory."; + for (File f : files) { + System.out.println((f.isDirectory() ? " " : " ") + f.getName()); } + } - @Override - public String usage() { - return "dir"; - } + @Override + public String description() { + return "Display the contents of working directory."; + } + + @Override + public String usage() { + return "dir"; + } } diff --git a/src/main/java/com/mycmd/commands/DriverqueryCommand.java b/src/main/java/com/mycmd/commands/DriverqueryCommand.java index 2360565..03769cd 100644 --- a/src/main/java/com/mycmd/commands/DriverqueryCommand.java +++ b/src/main/java/com/mycmd/commands/DriverqueryCommand.java @@ -13,47 +13,46 @@ */ public class DriverqueryCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); - - if (!os.contains("win")) { - System.out.println("driverquery is only available on Windows systems."); - return; - } - - try { - StringBuilder cmdBuilder = new StringBuilder("driverquery"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } - - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } - - int exitCode = process.waitFor(); - if (exitCode != 0) { - System.out.println("Command exited with code: " + exitCode); - } - - } catch (Exception e) { - System.out.println("Error executing driverquery: " + e.getMessage()); - } - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - @Override - public String description() { - return "Displays a list of all installed device drivers."; + if (!os.contains("win")) { + System.out.println("driverquery is only available on Windows systems."); + return; } - @Override - public String usage() { - return "driverquery [/v]"; + try { + StringBuilder cmdBuilder = new StringBuilder("driverquery"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } + + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + + int exitCode = process.waitFor(); + if (exitCode != 0) { + System.out.println("Command exited with code: " + exitCode); + } + + } catch (Exception e) { + System.out.println("Error executing driverquery: " + e.getMessage()); } + } + + @Override + public String description() { + return "Displays a list of all installed device drivers."; + } + + @Override + public String usage() { + return "driverquery [/v]"; + } } diff --git a/src/main/java/com/mycmd/commands/EchoCommand.java b/src/main/java/com/mycmd/commands/EchoCommand.java index 87dad81..5948f01 100644 --- a/src/main/java/com/mycmd/commands/EchoCommand.java +++ b/src/main/java/com/mycmd/commands/EchoCommand.java @@ -14,22 +14,22 @@ *

Multiple words are automatically joined with spaces between them. */ public class EchoCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length == 0) { - System.out.println(); - } else { - System.out.println(String.join(" ", args)); - } + @Override + public void execute(String[] args, ShellContext context) { + if (args.length == 0) { + System.out.println(); + } else { + System.out.println(String.join(" ", args)); } + } - @Override - public String description() { - return "Display a line of text"; - } + @Override + public String description() { + return "Display a line of text"; + } - @Override - public String usage() { - return "echo "; - } + @Override + public String usage() { + return "echo "; + } } diff --git a/src/main/java/com/mycmd/commands/ExitCommand.java b/src/main/java/com/mycmd/commands/ExitCommand.java index f18dc54..f0dca8f 100644 --- a/src/main/java/com/mycmd/commands/ExitCommand.java +++ b/src/main/java/com/mycmd/commands/ExitCommand.java @@ -15,19 +15,19 @@ * confirmation. */ public class ExitCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - System.out.println("Exiting MyCMD..."); - System.exit(0); - } + @Override + public void execute(String[] args, ShellContext context) { + System.out.println("Exiting MyCMD..."); + System.exit(0); + } - @Override - public String description() { - return "Exit the program."; - } + @Override + public String description() { + return "Exit the program."; + } - @Override - public String usage() { - return "exit"; - } + @Override + public String usage() { + return "exit"; + } } diff --git a/src/main/java/com/mycmd/commands/FcCommand.java b/src/main/java/com/mycmd/commands/FcCommand.java index 59d46ae..4a3139e 100644 --- a/src/main/java/com/mycmd/commands/FcCommand.java +++ b/src/main/java/com/mycmd/commands/FcCommand.java @@ -13,151 +13,151 @@ */ public class FcCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Compares two files or sets of files and displays the differences."); - System.out.println("\nFC [/A] [/B] [/C] [/L] [/LBn] [/N] [/T] [/W] [/nnnn]"); - System.out.println(" [drive1:][path1]filename1 [drive2:][path2]filename2"); - System.out.println( - "\n /A Displays only first and last lines for each set of differences."); - System.out.println(" /B Performs a binary comparison."); - System.out.println(" /C Disregards the case of letters."); - System.out.println(" /L Compares files as ASCII text."); - System.out.println(" /N Displays the line numbers on an ASCII comparison."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Compares two files or sets of files and displays the differences."); + System.out.println("\nFC [/A] [/B] [/C] [/L] [/LBn] [/N] [/T] [/W] [/nnnn]"); + System.out.println(" [drive1:][path1]filename1 [drive2:][path2]filename2"); + System.out.println( + "\n /A Displays only first and last lines for each set of differences."); + System.out.println(" /B Performs a binary comparison."); + System.out.println(" /C Disregards the case of letters."); + System.out.println(" /L Compares files as ASCII text."); + System.out.println(" /N Displays the line numbers on an ASCII comparison."); + return; + } - boolean binary = false; - boolean ignoreCase = false; - boolean showLineNumbers = false; - int argIndex = 0; - - // Parse flags - while (argIndex < args.length && args[argIndex].startsWith("/")) { - String flag = args[argIndex].toUpperCase(); - if (flag.equals("/B")) binary = true; - else if (flag.equals("/C")) ignoreCase = true; - else if (flag.equals("/N")) showLineNumbers = true; - argIndex++; - } + boolean binary = false; + boolean ignoreCase = false; + boolean showLineNumbers = false; + int argIndex = 0; + + // Parse flags + while (argIndex < args.length && args[argIndex].startsWith("/")) { + String flag = args[argIndex].toUpperCase(); + if (flag.equals("/B")) binary = true; + else if (flag.equals("/C")) ignoreCase = true; + else if (flag.equals("/N")) showLineNumbers = true; + argIndex++; + } - if (argIndex + 1 >= args.length) { - System.out.println("Insufficient parameters."); - return; - } + if (argIndex + 1 >= args.length) { + System.out.println("Insufficient parameters."); + return; + } - String file1Name = args[argIndex]; - String file2Name = args[argIndex + 1]; + String file1Name = args[argIndex]; + String file2Name = args[argIndex + 1]; - java.io.File file1 = new java.io.File(file1Name); - java.io.File file2 = new java.io.File(file2Name); + java.io.File file1 = new java.io.File(file1Name); + java.io.File file2 = new java.io.File(file2Name); - if (!file1.isAbsolute()) { - file1 = new java.io.File(context.getCurrentDir(), file1Name); - } - if (!file2.isAbsolute()) { - file2 = new java.io.File(context.getCurrentDir(), file2Name); - } + if (!file1.isAbsolute()) { + file1 = new java.io.File(context.getCurrentDir(), file1Name); + } + if (!file2.isAbsolute()) { + file2 = new java.io.File(context.getCurrentDir(), file2Name); + } - if (!file1.exists()) { - System.out.println("Cannot find " + file1Name); - return; - } - if (!file2.exists()) { - System.out.println("Cannot find " + file2Name); - return; - } + if (!file1.exists()) { + System.out.println("Cannot find " + file1Name); + return; + } + if (!file2.exists()) { + System.out.println("Cannot find " + file2Name); + return; + } - System.out.println("Comparing files " + file1.getName() + " and " + file2.getName()); + System.out.println("Comparing files " + file1.getName() + " and " + file2.getName()); - if (binary) { - compareBinary(file1, file2); - } else { - compareText(file1, file2, ignoreCase, showLineNumbers); - } + if (binary) { + compareBinary(file1, file2); + } else { + compareText(file1, file2, ignoreCase, showLineNumbers); } + } - private void compareBinary(java.io.File file1, java.io.File file2) throws IOException { - if (file1.length() != file2.length()) { - System.out.println("Files are different sizes."); - return; - } + private void compareBinary(java.io.File file1, java.io.File file2) throws IOException { + if (file1.length() != file2.length()) { + System.out.println("Files are different sizes."); + return; + } + + try (java.io.FileInputStream fis1 = new java.io.FileInputStream(file1); + java.io.FileInputStream fis2 = new java.io.FileInputStream(file2)) { + + int b1, b2; + long position = 0; + boolean different = false; - try (java.io.FileInputStream fis1 = new java.io.FileInputStream(file1); - java.io.FileInputStream fis2 = new java.io.FileInputStream(file2)) { - - int b1, b2; - long position = 0; - boolean different = false; - - while ((b1 = fis1.read()) != -1) { - b2 = fis2.read(); - if (b1 != b2) { - System.out.println("Files differ at position " + position); - different = true; - break; - } - position++; - } - - if (!different) { - System.out.println("FC: no differences encountered"); - } + while ((b1 = fis1.read()) != -1) { + b2 = fis2.read(); + if (b1 != b2) { + System.out.println("Files differ at position " + position); + different = true; + break; } + position++; + } + + if (!different) { + System.out.println("FC: no differences encountered"); + } } + } + + private void compareText( + java.io.File file1, java.io.File file2, boolean ignoreCase, boolean showLineNumbers) + throws IOException { + try (BufferedReader reader1 = new BufferedReader(new FileReader(file1)); + BufferedReader reader2 = new BufferedReader(new FileReader(file2))) { + + String line1, line2; + int lineNum = 0; + boolean different = false; - private void compareText( - java.io.File file1, java.io.File file2, boolean ignoreCase, boolean showLineNumbers) - throws IOException { - try (BufferedReader reader1 = new BufferedReader(new FileReader(file1)); - BufferedReader reader2 = new BufferedReader(new FileReader(file2))) { - - String line1, line2; - int lineNum = 0; - boolean different = false; - - while (true) { - line1 = reader1.readLine(); - line2 = reader2.readLine(); - lineNum++; - - if (line1 == null && line2 == null) break; - - if (line1 == null || line2 == null) { - System.out.println("Files are different lengths."); - different = true; - break; - } - - String compare1 = ignoreCase ? line1.toLowerCase() : line1; - String compare2 = ignoreCase ? line2.toLowerCase() : line2; - - if (!compare1.equals(compare2)) { - System.out.println("***** " + file1.getName()); - if (showLineNumbers) System.out.print(lineNum + ": "); - System.out.println(line1); - System.out.println("***** " + file2.getName()); - if (showLineNumbers) System.out.print(lineNum + ": "); - System.out.println(line2); - System.out.println("*****\n"); - different = true; - } - } - - if (!different) { - System.out.println("FC: no differences encountered"); - } + while (true) { + line1 = reader1.readLine(); + line2 = reader2.readLine(); + lineNum++; + + if (line1 == null && line2 == null) break; + + if (line1 == null || line2 == null) { + System.out.println("Files are different lengths."); + different = true; + break; } - } - @Override - public String description() { - return "Compares two files or sets of files and displays the differences."; - } + String compare1 = ignoreCase ? line1.toLowerCase() : line1; + String compare2 = ignoreCase ? line2.toLowerCase() : line2; + + if (!compare1.equals(compare2)) { + System.out.println("***** " + file1.getName()); + if (showLineNumbers) System.out.print(lineNum + ": "); + System.out.println(line1); + System.out.println("***** " + file2.getName()); + if (showLineNumbers) System.out.print(lineNum + ": "); + System.out.println(line2); + System.out.println("*****\n"); + different = true; + } + } - @Override - public String usage() { - return "fc [/B] [/C] [/N] file1 file2"; + if (!different) { + System.out.println("FC: no differences encountered"); + } } + } + + @Override + public String description() { + return "Compares two files or sets of files and displays the differences."; + } + + @Override + public String usage() { + return "fc [/B] [/C] [/N] file1 file2"; + } } diff --git a/src/main/java/com/mycmd/commands/FindCommand.java b/src/main/java/com/mycmd/commands/FindCommand.java index 9c45c68..ad511d8 100644 --- a/src/main/java/com/mycmd/commands/FindCommand.java +++ b/src/main/java/com/mycmd/commands/FindCommand.java @@ -14,120 +14,117 @@ */ public class FindCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Searches for a text string in a file or files."); - System.out.println( - "\nFIND [/V] [/C] [/N] [/I] [/OFF[LINE]] \"string\" [[drive:][path]filename[ ...]]"); - System.out.println( - "\n /V Displays all lines NOT containing the specified string."); - System.out.println( - " /C Displays only the count of lines containing the string."); - System.out.println(" /N Displays line numbers with the displayed lines."); - System.out.println( - " /I Ignores the case of characters when searching for the string."); - System.out.println(" \"string\" Specifies the text string to find."); - System.out.println(" [drive:][path]filename"); - System.out.println(" Specifies a file or files to search."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Searches for a text string in a file or files."); + System.out.println( + "\nFIND [/V] [/C] [/N] [/I] [/OFF[LINE]] \"string\" [[drive:][path]filename[ ...]]"); + System.out.println("\n /V Displays all lines NOT containing the specified string."); + System.out.println(" /C Displays only the count of lines containing the string."); + System.out.println(" /N Displays line numbers with the displayed lines."); + System.out.println( + " /I Ignores the case of characters when searching for the string."); + System.out.println(" \"string\" Specifies the text string to find."); + System.out.println(" [drive:][path]filename"); + System.out.println(" Specifies a file or files to search."); + return; + } - boolean caseInsensitive = false; - boolean showLineNumbers = false; - boolean countOnly = false; - boolean invertMatch = false; - int argIndex = 0; - - // Parse flags - while (argIndex < args.length && args[argIndex].startsWith("/")) { - String flag = args[argIndex].toUpperCase(); - if (flag.equals("/I")) caseInsensitive = true; - else if (flag.equals("/N")) showLineNumbers = true; - else if (flag.equals("/C")) countOnly = true; - else if (flag.equals("/V")) invertMatch = true; - argIndex++; - } + boolean caseInsensitive = false; + boolean showLineNumbers = false; + boolean countOnly = false; + boolean invertMatch = false; + int argIndex = 0; + + // Parse flags + while (argIndex < args.length && args[argIndex].startsWith("/")) { + String flag = args[argIndex].toUpperCase(); + if (flag.equals("/I")) caseInsensitive = true; + else if (flag.equals("/N")) showLineNumbers = true; + else if (flag.equals("/C")) countOnly = true; + else if (flag.equals("/V")) invertMatch = true; + argIndex++; + } - if (argIndex >= args.length) { - System.out.println("Missing search string."); - return; - } + if (argIndex >= args.length) { + System.out.println("Missing search string."); + return; + } - String searchString = args[argIndex++].replace("\"", ""); + String searchString = args[argIndex++].replace("\"", ""); - if (argIndex >= args.length) { - System.out.println("Missing filename."); - return; - } + if (argIndex >= args.length) { + System.out.println("Missing filename."); + return; + } - // Process files - for (int i = argIndex; i < args.length; i++) { - String filename = args[i]; - java.io.File file = new java.io.File(filename); + // Process files + for (int i = argIndex; i < args.length; i++) { + String filename = args[i]; + java.io.File file = new java.io.File(filename); - if (!file.isAbsolute()) { - file = new java.io.File(context.getCurrentDir(), filename); - } + if (!file.isAbsolute()) { + file = new java.io.File(context.getCurrentDir(), filename); + } - if (!file.exists()) { - System.out.println("File not found - " + filename); - continue; - } + if (!file.exists()) { + System.out.println("File not found - " + filename); + continue; + } - searchInFile( - file, searchString, caseInsensitive, showLineNumbers, countOnly, invertMatch); - } + searchInFile(file, searchString, caseInsensitive, showLineNumbers, countOnly, invertMatch); } - - private void searchInFile( - java.io.File file, - String searchString, - boolean caseInsensitive, - boolean showLineNumbers, - boolean countOnly, - boolean invertMatch) - throws IOException { - System.out.println("\n---------- " + file.getName().toUpperCase()); - - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - int lineNumber = 0; - int matchCount = 0; - - while ((line = reader.readLine()) != null) { - lineNumber++; - String compareLine = caseInsensitive ? line.toLowerCase() : line; - String compareString = caseInsensitive ? searchString.toLowerCase() : searchString; - - boolean matches = compareLine.contains(compareString); - if (invertMatch) matches = !matches; - - if (matches) { - matchCount++; - if (!countOnly) { - if (showLineNumbers) { - System.out.println("[" + lineNumber + "]" + line); - } else { - System.out.println(line); - } - } - } - } - - if (countOnly) { - System.out.println("Count: " + matchCount); + } + + private void searchInFile( + java.io.File file, + String searchString, + boolean caseInsensitive, + boolean showLineNumbers, + boolean countOnly, + boolean invertMatch) + throws IOException { + System.out.println("\n---------- " + file.getName().toUpperCase()); + + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + int lineNumber = 0; + int matchCount = 0; + + while ((line = reader.readLine()) != null) { + lineNumber++; + String compareLine = caseInsensitive ? line.toLowerCase() : line; + String compareString = caseInsensitive ? searchString.toLowerCase() : searchString; + + boolean matches = compareLine.contains(compareString); + if (invertMatch) matches = !matches; + + if (matches) { + matchCount++; + if (!countOnly) { + if (showLineNumbers) { + System.out.println("[" + lineNumber + "]" + line); + } else { + System.out.println(line); } + } } - } + } - @Override - public String description() { - return "Searches for a text string in a file or files."; + if (countOnly) { + System.out.println("Count: " + matchCount); + } } + } - @Override - public String usage() { - return "find [/I] [/N] [/C] \"string\" filename"; - } + @Override + public String description() { + return "Searches for a text string in a file or files."; + } + + @Override + public String usage() { + return "find [/I] [/N] [/C] \"string\" filename"; + } } diff --git a/src/main/java/com/mycmd/commands/FindstrCommand.java b/src/main/java/com/mycmd/commands/FindstrCommand.java index 40808d8..ac1240f 100644 --- a/src/main/java/com/mycmd/commands/FindstrCommand.java +++ b/src/main/java/com/mycmd/commands/FindstrCommand.java @@ -16,124 +16,120 @@ */ public class FindstrCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Searches for strings in files."); - System.out.println( - "\nFINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P]"); - System.out.println(" [/F:file] [/C:string] [/G:file] [/D:dir list] [strings]"); - System.out.println(" [[drive:][path]filename[ ...]]"); - System.out.println( - "\n /I Specifies that the search is not to be case-sensitive."); - System.out.println( - " /N Prints the line number before each line that matches."); - System.out.println(" /R Uses search strings as regular expressions."); - System.out.println( - " /S Searches for matching files in the current directory and all"); - System.out.println(" subdirectories."); - System.out.println(" strings Text to be searched for."); - System.out.println(" [drive:][path]filename"); - System.out.println(" Specifies a file or files to search."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Searches for strings in files."); + System.out.println("\nFINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P]"); + System.out.println(" [/F:file] [/C:string] [/G:file] [/D:dir list] [strings]"); + System.out.println(" [[drive:][path]filename[ ...]]"); + System.out.println("\n /I Specifies that the search is not to be case-sensitive."); + System.out.println(" /N Prints the line number before each line that matches."); + System.out.println(" /R Uses search strings as regular expressions."); + System.out.println( + " /S Searches for matching files in the current directory and all"); + System.out.println(" subdirectories."); + System.out.println(" strings Text to be searched for."); + System.out.println(" [drive:][path]filename"); + System.out.println(" Specifies a file or files to search."); + return; + } - boolean caseInsensitive = false; - boolean showLineNumbers = false; - boolean useRegex = false; - boolean recursive = false; - int argIndex = 0; - - // Parse flags - while (argIndex < args.length && args[argIndex].startsWith("/")) { - String flag = args[argIndex].toUpperCase(); - if (flag.equals("/I")) caseInsensitive = true; - else if (flag.equals("/N")) showLineNumbers = true; - else if (flag.equals("/R")) useRegex = true; - else if (flag.equals("/S")) recursive = true; - argIndex++; - } + boolean caseInsensitive = false; + boolean showLineNumbers = false; + boolean useRegex = false; + boolean recursive = false; + int argIndex = 0; + + // Parse flags + while (argIndex < args.length && args[argIndex].startsWith("/")) { + String flag = args[argIndex].toUpperCase(); + if (flag.equals("/I")) caseInsensitive = true; + else if (flag.equals("/N")) showLineNumbers = true; + else if (flag.equals("/R")) useRegex = true; + else if (flag.equals("/S")) recursive = true; + argIndex++; + } - if (argIndex >= args.length) { - System.out.println("Missing search string."); - return; - } + if (argIndex >= args.length) { + System.out.println("Missing search string."); + return; + } - String searchString = args[argIndex++].replace("\"", ""); + String searchString = args[argIndex++].replace("\"", ""); - if (argIndex >= args.length) { - System.out.println("Missing filename."); - return; - } + if (argIndex >= args.length) { + System.out.println("Missing filename."); + return; + } - Pattern pattern = null; - if (useRegex) { - int flags = caseInsensitive ? Pattern.CASE_INSENSITIVE : 0; - pattern = Pattern.compile(searchString, flags); - } + Pattern pattern = null; + if (useRegex) { + int flags = caseInsensitive ? Pattern.CASE_INSENSITIVE : 0; + pattern = Pattern.compile(searchString, flags); + } - // Process files - for (int i = argIndex; i < args.length; i++) { - String filename = args[i]; - java.io.File file = new java.io.File(filename); + // Process files + for (int i = argIndex; i < args.length; i++) { + String filename = args[i]; + java.io.File file = new java.io.File(filename); - if (!file.isAbsolute()) { - file = new java.io.File(context.getCurrentDir(), filename); - } + if (!file.isAbsolute()) { + file = new java.io.File(context.getCurrentDir(), filename); + } - if (!file.exists()) { - System.out.println("File not found - " + filename); - continue; - } + if (!file.exists()) { + System.out.println("File not found - " + filename); + continue; + } - searchInFile(file, searchString, pattern, caseInsensitive, showLineNumbers, useRegex); - } + searchInFile(file, searchString, pattern, caseInsensitive, showLineNumbers, useRegex); } + } + + private void searchInFile( + java.io.File file, + String searchString, + Pattern pattern, + boolean caseInsensitive, + boolean showLineNumbers, + boolean useRegex) + throws IOException { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + int lineNumber = 0; + + while ((line = reader.readLine()) != null) { + lineNumber++; + boolean matches = false; + + if (useRegex && pattern != null) { + Matcher matcher = pattern.matcher(line); + matches = matcher.find(); + } else { + String compareLine = caseInsensitive ? line.toLowerCase() : line; + String compareString = caseInsensitive ? searchString.toLowerCase() : searchString; + matches = compareLine.contains(compareString); + } - private void searchInFile( - java.io.File file, - String searchString, - Pattern pattern, - boolean caseInsensitive, - boolean showLineNumbers, - boolean useRegex) - throws IOException { - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - int lineNumber = 0; - - while ((line = reader.readLine()) != null) { - lineNumber++; - boolean matches = false; - - if (useRegex && pattern != null) { - Matcher matcher = pattern.matcher(line); - matches = matcher.find(); - } else { - String compareLine = caseInsensitive ? line.toLowerCase() : line; - String compareString = - caseInsensitive ? searchString.toLowerCase() : searchString; - matches = compareLine.contains(compareString); - } - - if (matches) { - if (showLineNumbers) { - System.out.println(file.getName() + ":" + lineNumber + ":" + line); - } else { - System.out.println(file.getName() + ":" + line); - } - } - } + if (matches) { + if (showLineNumbers) { + System.out.println(file.getName() + ":" + lineNumber + ":" + line); + } else { + System.out.println(file.getName() + ":" + line); + } } + } } + } - @Override - public String description() { - return "Searches for strings in files using regular expressions."; - } + @Override + public String description() { + return "Searches for strings in files using regular expressions."; + } - @Override - public String usage() { - return "findstr [/I] [/N] [/R] \"pattern\" filename"; - } + @Override + public String usage() { + return "findstr [/I] [/N] [/R] \"pattern\" filename"; + } } diff --git a/src/main/java/com/mycmd/commands/ForfilesCommand.java b/src/main/java/com/mycmd/commands/ForfilesCommand.java index 4d5f735..9d31526 100644 --- a/src/main/java/com/mycmd/commands/ForfilesCommand.java +++ b/src/main/java/com/mycmd/commands/ForfilesCommand.java @@ -13,75 +13,71 @@ */ public class ForfilesCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - System.out.println("FORFILES [/P pathname] [/M searchmask] [/S]"); - System.out.println(" [/C command] [/D [+ | -] {MM/dd/yyyy | dd}]"); - System.out.println("\nDescription:"); - System.out.println(" Selects a file (or set of files) and executes a"); - System.out.println(" command on that file. This is helpful for batch jobs."); - System.out.println("\nParameter List:"); - System.out.println(" /P pathname Indicates the path to start searching."); - System.out.println(" /M searchmask Searches files according to a searchmask."); - System.out.println(" /S Recurses into subdirectories."); - System.out.println( - " /C command Indicates the command to execute for each file."); - System.out.println( - " /D date Selects files with a last modified date greater"); - System.out.println( - " than or equal to (+), or less than or equal to"); - System.out.println(" (-), the specified date."); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + System.out.println("FORFILES [/P pathname] [/M searchmask] [/S]"); + System.out.println(" [/C command] [/D [+ | -] {MM/dd/yyyy | dd}]"); + System.out.println("\nDescription:"); + System.out.println(" Selects a file (or set of files) and executes a"); + System.out.println(" command on that file. This is helpful for batch jobs."); + System.out.println("\nParameter List:"); + System.out.println(" /P pathname Indicates the path to start searching."); + System.out.println(" /M searchmask Searches files according to a searchmask."); + System.out.println(" /S Recurses into subdirectories."); + System.out.println(" /C command Indicates the command to execute for each file."); + System.out.println(" /D date Selects files with a last modified date greater"); + System.out.println(" than or equal to (+), or less than or equal to"); + System.out.println(" (-), the specified date."); - if (args.length == 0) { - return; - } + if (args.length == 0) { + return; + } - String os = System.getProperty("os.name").toLowerCase(); + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("\nFORFILES is only available on Windows systems."); - System.out.println("On Unix-like systems, use 'find' with '-exec' instead."); - return; - } + if (!os.contains("win")) { + System.out.println("\nFORFILES is only available on Windows systems."); + System.out.println("On Unix-like systems, use 'find' with '-exec' instead."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("forfiles"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + StringBuilder cmdBuilder = new StringBuilder("forfiles"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - pb.directory(context.getCurrentDir()); - Process process = pb.start(); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + pb.directory(context.getCurrentDir()); + Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing forfiles: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing forfiles: " + e.getMessage()); } + } - @Override - public String description() { - return "Selects files in a directory and runs a command on each file."; - } + @Override + public String description() { + return "Selects files in a directory and runs a command on each file."; + } - @Override - public String usage() { - return "forfiles [/P pathname] [/M searchmask] [/S] [/C command]"; - } + @Override + public String usage() { + return "forfiles [/P pathname] [/M searchmask] [/S] [/C command]"; + } } diff --git a/src/main/java/com/mycmd/commands/FsutilCommand.java b/src/main/java/com/mycmd/commands/FsutilCommand.java index 2f4f784..4a1732e 100644 --- a/src/main/java/com/mycmd/commands/FsutilCommand.java +++ b/src/main/java/com/mycmd/commands/FsutilCommand.java @@ -13,61 +13,60 @@ */ public class FsutilCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("FSUTIL is only available on Windows systems."); - return; - } + if (!os.contains("win")) { + System.out.println("FSUTIL is only available on Windows systems."); + return; + } - if (args.length == 0) { - System.out.println("---- FSUTIL Commands Supported ----"); - System.out.println("\nfsinfo File System Information"); - System.out.println("volume Volume management"); - System.out.println("file File specific commands"); - System.out.println("hardlink Hardlink management"); - System.out.println("usn USN management"); - System.out.println("\nNote: Administrator privileges required for most operations."); - return; - } + if (args.length == 0) { + System.out.println("---- FSUTIL Commands Supported ----"); + System.out.println("\nfsinfo File System Information"); + System.out.println("volume Volume management"); + System.out.println("file File specific commands"); + System.out.println("hardlink Hardlink management"); + System.out.println("usn USN management"); + System.out.println("\nNote: Administrator privileges required for most operations."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("fsutil"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + StringBuilder cmdBuilder = new StringBuilder("fsutil"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing fsutil: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing fsutil: " + e.getMessage()); } + } - @Override - public String description() { - return "File System Utility - Performs file system operations."; - } + @Override + public String description() { + return "File System Utility - Performs file system operations."; + } - @Override - public String usage() { - return "fsutil [command] [options]"; - } + @Override + public String usage() { + return "fsutil [command] [options]"; + } } diff --git a/src/main/java/com/mycmd/commands/FtypeCommand.java b/src/main/java/com/mycmd/commands/FtypeCommand.java index 9d543cf..7344856 100644 --- a/src/main/java/com/mycmd/commands/FtypeCommand.java +++ b/src/main/java/com/mycmd/commands/FtypeCommand.java @@ -13,44 +13,43 @@ */ public class FtypeCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); - - if (!os.contains("win")) { - System.out.println("FTYPE is only available on Windows systems."); - return; - } - - try { - StringBuilder cmdBuilder = new StringBuilder("ftype"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } - - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } - - process.waitFor(); - - } catch (Exception e) { - System.out.println("Error executing ftype: " + e.getMessage()); - } - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - @Override - public String description() { - return "Displays or modifies file types used in file extension associations."; + if (!os.contains("win")) { + System.out.println("FTYPE is only available on Windows systems."); + return; } - @Override - public String usage() { - return "ftype [fileType[=[openCommandString]]]"; + try { + StringBuilder cmdBuilder = new StringBuilder("ftype"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } + + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + + process.waitFor(); + + } catch (Exception e) { + System.out.println("Error executing ftype: " + e.getMessage()); } + } + + @Override + public String description() { + return "Displays or modifies file types used in file extension associations."; + } + + @Override + public String usage() { + return "ftype [fileType[=[openCommandString]]]"; + } } diff --git a/src/main/java/com/mycmd/commands/GetmacCommand.java b/src/main/java/com/mycmd/commands/GetmacCommand.java index dcd5799..156ae91 100644 --- a/src/main/java/com/mycmd/commands/GetmacCommand.java +++ b/src/main/java/com/mycmd/commands/GetmacCommand.java @@ -15,65 +15,62 @@ */ public class GetmacCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - try { - StringBuilder cmdBuilder = new StringBuilder("getmac"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + if (os.contains("win")) { + try { + StringBuilder cmdBuilder = new StringBuilder("getmac"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - Process process = pb.start(); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing getmac: " + e.getMessage()); - } - } else { - // Cross-platform implementation - System.out.println("Network Adapter MAC Addresses:\n"); - try { - Enumeration networks = NetworkInterface.getNetworkInterfaces(); - while (networks.hasMoreElements()) { - NetworkInterface network = networks.nextElement(); - byte[] mac = network.getHardwareAddress(); + } catch (Exception e) { + System.out.println("Error executing getmac: " + e.getMessage()); + } + } else { + // Cross-platform implementation + System.out.println("Network Adapter MAC Addresses:\n"); + try { + Enumeration networks = NetworkInterface.getNetworkInterfaces(); + while (networks.hasMoreElements()) { + NetworkInterface network = networks.nextElement(); + byte[] mac = network.getHardwareAddress(); - if (mac != null) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < mac.length; i++) { - sb.append( - String.format( - "%02X%s", mac[i], (i < mac.length - 1) ? "-" : "")); - } - System.out.printf("%-20s %s%n", network.getName(), sb.toString()); - } - } - } catch (Exception e) { - System.out.println("Error retrieving MAC addresses: " + e.getMessage()); + if (mac != null) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < mac.length; i++) { + sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : "")); } + System.out.printf("%-20s %s%n", network.getName(), sb.toString()); + } } + } catch (Exception e) { + System.out.println("Error retrieving MAC addresses: " + e.getMessage()); + } } + } - @Override - public String description() { - return "Displays MAC addresses for all network adapters."; - } + @Override + public String description() { + return "Displays MAC addresses for all network adapters."; + } - @Override - public String usage() { - return "getmac [/V]"; - } + @Override + public String usage() { + return "getmac [/V]"; + } } diff --git a/src/main/java/com/mycmd/commands/HelpCommand.java b/src/main/java/com/mycmd/commands/HelpCommand.java index 49be563..ab8701b 100644 --- a/src/main/java/com/mycmd/commands/HelpCommand.java +++ b/src/main/java/com/mycmd/commands/HelpCommand.java @@ -9,51 +9,51 @@ * descriptions. Supports detailed help for individual commands using 'help '. */ public class HelpCommand implements Command { - private final Map commands; - - public HelpCommand(Map commands) { - this.commands = commands; - } - - @Override - public void execute(String[] args, ShellContext context) { - // Detailed help for a specific command - if (args.length > 0) { - String cmdName = args[0]; - Command cmd = commands.get(cmdName); - - if (cmd != null) { - System.out.println("\nCommand: " + cmdName); - System.out.println("Description: " + cmd.description()); - System.out.println( - "Usage: " + (cmd.usage() != null ? cmd.usage() : cmdName + " [options]")); - } else { - System.out.println("No such command: " + cmdName); - } - return; - } - - // General help listing all commands - System.out.println("\nMyCMD โ€” Available Commands:\n"); - for (Map.Entry entry : commands.entrySet()) { - String name = entry.getKey(); - Command cmd = entry.getValue(); - String description = - (cmd.description() != null && !cmd.description().isEmpty()) - ? cmd.description() - : "No description available"; - System.out.printf(" %-12s : %s%n", name, description); - } - System.out.println("\nType 'help ' for detailed info about a specific command.\n"); - } - - @Override - public String description() { - return "Show list of available commands and their descriptions."; + private final Map commands; + + public HelpCommand(Map commands) { + this.commands = commands; + } + + @Override + public void execute(String[] args, ShellContext context) { + // Detailed help for a specific command + if (args.length > 0) { + String cmdName = args[0]; + Command cmd = commands.get(cmdName); + + if (cmd != null) { + System.out.println("\nCommand: " + cmdName); + System.out.println("Description: " + cmd.description()); + System.out.println( + "Usage: " + (cmd.usage() != null ? cmd.usage() : cmdName + " [options]")); + } else { + System.out.println("No such command: " + cmdName); + } + return; } - @Override - public String usage() { - return "help [command]"; + // General help listing all commands + System.out.println("\nMyCMD โ€” Available Commands:\n"); + for (Map.Entry entry : commands.entrySet()) { + String name = entry.getKey(); + Command cmd = entry.getValue(); + String description = + (cmd.description() != null && !cmd.description().isEmpty()) + ? cmd.description() + : "No description available"; + System.out.printf(" %-12s : %s%n", name, description); } + System.out.println("\nType 'help ' for detailed info about a specific command.\n"); + } + + @Override + public String description() { + return "Show list of available commands and their descriptions."; + } + + @Override + public String usage() { + return "help [command]"; + } } diff --git a/src/main/java/com/mycmd/commands/HistoryCommand.java b/src/main/java/com/mycmd/commands/HistoryCommand.java index b0a1270..155e432 100644 --- a/src/main/java/com/mycmd/commands/HistoryCommand.java +++ b/src/main/java/com/mycmd/commands/HistoryCommand.java @@ -5,29 +5,29 @@ public class HistoryCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - // Get the command history from the context - var history = context.getCommandHistory(); + @Override + public void execute(String[] args, ShellContext context) { + // Get the command history from the context + var history = context.getCommandHistory(); - if (history.isEmpty()) { - System.out.println("No commands in history."); - return; - } - - // Display the history with numbers - for (int i = 0; i < history.size(); i++) { - System.out.println((i + 1) + ". " + history.get(i)); - } + if (history.isEmpty()) { + System.out.println("No commands in history."); + return; } - @Override - public String description() { - return "Display the list of previously executed commands."; + // Display the history with numbers + for (int i = 0; i < history.size(); i++) { + System.out.println((i + 1) + ". " + history.get(i)); } + } - @Override - public String usage() { - return "history"; - } + @Override + public String description() { + return "Display the list of previously executed commands."; + } + + @Override + public String usage() { + return "history"; + } } diff --git a/src/main/java/com/mycmd/commands/HostnameCommand.java b/src/main/java/com/mycmd/commands/HostnameCommand.java index 306688a..0a7911c 100644 --- a/src/main/java/com/mycmd/commands/HostnameCommand.java +++ b/src/main/java/com/mycmd/commands/HostnameCommand.java @@ -17,26 +17,26 @@ * is typically set. */ public class HostnameCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - String hostname = System.getenv("COMPUTERNAME"); - if (hostname == null) { - try { - hostname = InetAddress.getLocalHost().getHostName(); - } catch (Exception e) { - hostname = "Unknown Host"; - } - } - System.out.println(hostname); + @Override + public void execute(String[] args, ShellContext context) { + String hostname = System.getenv("COMPUTERNAME"); + if (hostname == null) { + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (Exception e) { + hostname = "Unknown Host"; + } } + System.out.println(hostname); + } - @Override - public String description() { - return "Display the hostname of the current computer."; - } + @Override + public String description() { + return "Display the hostname of the current computer."; + } - @Override - public String usage() { - return "hostname"; - } + @Override + public String usage() { + return "hostname"; + } } diff --git a/src/main/java/com/mycmd/commands/InteractiveSearchCommand.java b/src/main/java/com/mycmd/commands/InteractiveSearchCommand.java index fd69622..3fc88cb 100644 --- a/src/main/java/com/mycmd/commands/InteractiveSearchCommand.java +++ b/src/main/java/com/mycmd/commands/InteractiveSearchCommand.java @@ -1,127 +1,126 @@ -package com.mycmd.commands; - -import com.mycmd.Command; -import com.mycmd.ShellContext; -import java.util.List; -import java.util.Scanner; -import java.util.stream.Collectors; - -/** - * Interactive history search command (similar to Ctrl+R in bash). - * Usage: isearch - * - * Provides an interactive prompt where users can: - * - Type to filter history in real-time - * - Navigate through matches with numbers - * - Execute a selected command - */ -public class InteractiveSearchCommand implements Command { - - @Override - public void execute(String[] args, ShellContext context) { - List history = context.getHistory(); - - if (history.isEmpty()) { - System.out.println("No command history available."); - return; - } - - // โœ… Use shared scanner from ShellContext instead of creating a new one - Scanner scanner = context.getScanner(); - - System.out.println("=== Interactive History Search ==="); - System.out.println("Type to search, 'q' to quit"); - System.out.println(); - - while (true) { - System.out.print("search> "); - String searchTerm = scanner.nextLine().trim(); - - if (searchTerm.equalsIgnoreCase("q") || searchTerm.equalsIgnoreCase("quit")) { - System.out.println("Search cancelled."); - break; - } - - if (searchTerm.isEmpty()) { - System.out.println("Enter a search term or 'q' to quit."); - continue; - } - - // Search and display results - List matches = searchHistory(history, searchTerm); - - if (matches.isEmpty()) { - System.out.println("No matches found for: '" + searchTerm + "'"); - System.out.println(); - continue; - } - - // Display matches with numbers - System.out.println("\nMatches for '" + searchTerm + "':"); - for (int i = 0; i < Math.min(matches.size(), 10); i++) { - System.out.println(" " + (i + 1) + ". " + matches.get(i)); - } - - if (matches.size() > 10) { - System.out.println(" ... and " + (matches.size() - 10) + " more"); - } - - // Ask user to select or refine - System.out.println(); - System.out.print("Select number to copy (1-" + Math.min(matches.size(), 10) + - "), or press Enter to search again: "); - String selection = scanner.nextLine().trim(); - - if (selection.isEmpty()) { - continue; - } - - try { - int index = Integer.parseInt(selection) - 1; - if (index >= 0 && index < Math.min(matches.size(), 10)) { - String selectedCommand = matches.get(index); - System.out.println("\nSelected command: " + selectedCommand); - System.out.println("(You can now run this command by typing it at the prompt)"); - break; - } else { - System.out.println("Invalid selection. Try again."); - } - } catch (NumberFormatException e) { - System.out.println("Invalid input. Enter a number or press Enter."); - } - - System.out.println(); - } - } - - /** - * Search history for commands containing the search term. - * Returns matches in reverse order (most recent first). - */ - private List searchHistory(List history, String searchTerm) { - String lowerSearch = searchTerm.toLowerCase(); - - // Search in reverse order (most recent first) - return history.stream() - .filter(cmd -> cmd.toLowerCase().contains(lowerSearch)) - .collect(Collectors.collectingAndThen( - Collectors.toList(), - list -> { - java.util.Collections.reverse(list); - return list; - } - )); - } - - @Override - public String description() { - return "Interactive history search (like Ctrl+R)"; - } - - @Override - public String usage() { - return "isearch\n" + - " Opens an interactive prompt to search command history.\n" + - " Type your search term and select from matching commands."; - } -} +package com.mycmd.commands; + +import com.mycmd.Command; +import com.mycmd.ShellContext; +import java.util.List; +import java.util.Scanner; +import java.util.stream.Collectors; + +/** + * Interactive history search command (similar to Ctrl+R in bash). Usage: isearch + * + *

Provides an interactive prompt where users can: - Type to filter history in real-time - + * Navigate through matches with numbers - Execute a selected command + */ +public class InteractiveSearchCommand implements Command { + + @Override + public void execute(String[] args, ShellContext context) { + List history = context.getHistory(); + + if (history.isEmpty()) { + System.out.println("No command history available."); + return; + } + + // โœ… Use shared scanner from ShellContext instead of creating a new one + Scanner scanner = context.getScanner(); + + System.out.println("=== Interactive History Search ==="); + System.out.println("Type to search, 'q' to quit"); + System.out.println(); + + while (true) { + System.out.print("search> "); + String searchTerm = scanner.nextLine().trim(); + + if (searchTerm.equalsIgnoreCase("q") || searchTerm.equalsIgnoreCase("quit")) { + System.out.println("Search cancelled."); + break; + } + + if (searchTerm.isEmpty()) { + System.out.println("Enter a search term or 'q' to quit."); + continue; + } + + // Search and display results + List matches = searchHistory(history, searchTerm); + + if (matches.isEmpty()) { + System.out.println("No matches found for: '" + searchTerm + "'"); + System.out.println(); + continue; + } + + // Display matches with numbers + System.out.println("\nMatches for '" + searchTerm + "':"); + for (int i = 0; i < Math.min(matches.size(), 10); i++) { + System.out.println(" " + (i + 1) + ". " + matches.get(i)); + } + + if (matches.size() > 10) { + System.out.println(" ... and " + (matches.size() - 10) + " more"); + } + + // Ask user to select or refine + System.out.println(); + System.out.print( + "Select number to copy (1-" + + Math.min(matches.size(), 10) + + "), or press Enter to search again: "); + String selection = scanner.nextLine().trim(); + + if (selection.isEmpty()) { + continue; + } + + try { + int index = Integer.parseInt(selection) - 1; + if (index >= 0 && index < Math.min(matches.size(), 10)) { + String selectedCommand = matches.get(index); + System.out.println("\nSelected command: " + selectedCommand); + System.out.println("(You can now run this command by typing it at the prompt)"); + break; + } else { + System.out.println("Invalid selection. Try again."); + } + } catch (NumberFormatException e) { + System.out.println("Invalid input. Enter a number or press Enter."); + } + + System.out.println(); + } + } + + /** + * Search history for commands containing the search term. Returns matches in reverse order (most + * recent first). + */ + private List searchHistory(List history, String searchTerm) { + String lowerSearch = searchTerm.toLowerCase(); + + // Search in reverse order (most recent first) + return history.stream() + .filter(cmd -> cmd.toLowerCase().contains(lowerSearch)) + .collect( + Collectors.collectingAndThen( + Collectors.toList(), + list -> { + java.util.Collections.reverse(list); + return list; + })); + } + + @Override + public String description() { + return "Interactive history search (like Ctrl+R)"; + } + + @Override + public String usage() { + return "isearch\n" + + " Opens an interactive prompt to search command history.\n" + + " Type your search term and select from matching commands."; + } +} diff --git a/src/main/java/com/mycmd/commands/IpConfig.java b/src/main/java/com/mycmd/commands/IpConfig.java index 09d9f50..272c82d 100644 --- a/src/main/java/com/mycmd/commands/IpConfig.java +++ b/src/main/java/com/mycmd/commands/IpConfig.java @@ -11,34 +11,34 @@ /** Implements the "ipconfig" command for MyCMD. */ public class IpConfig implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - try { - Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); - while (interfaces.hasMoreElements()) { - NetworkInterface ni = interfaces.nextElement(); - System.out.println("Interface: " + ni.getDisplayName()); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface ni = interfaces.nextElement(); + System.out.println("Interface: " + ni.getDisplayName()); - Enumeration addresses = ni.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress addr = addresses.nextElement(); - System.out.println(" IP Address: " + addr.getHostAddress()); - } - - System.out.println(); // blank line between interfaces - } - } catch (SocketException e) { - throw new IOException("Failed to get network interfaces", e); + Enumeration addresses = ni.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress addr = addresses.nextElement(); + System.out.println(" IP Address: " + addr.getHostAddress()); } - } - @Override - public String description() { - return "Displays all network interfaces and their IP addresses"; + System.out.println(); // blank line between interfaces + } + } catch (SocketException e) { + throw new IOException("Failed to get network interfaces", e); } + } - @Override - public String usage() { - return "ipconfig"; - } + @Override + public String description() { + return "Displays all network interfaces and their IP addresses"; + } + + @Override + public String usage() { + return "ipconfig"; + } } diff --git a/src/main/java/com/mycmd/commands/LabelCommand.java b/src/main/java/com/mycmd/commands/LabelCommand.java index 3391e54..8507a66 100644 --- a/src/main/java/com/mycmd/commands/LabelCommand.java +++ b/src/main/java/com/mycmd/commands/LabelCommand.java @@ -12,31 +12,31 @@ */ public class LabelCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - System.out.println("LABEL - Creates, changes, or deletes the volume label of a disk."); - System.out.println("\nNote: This is a read-only simulation."); - System.out.println("Actual volume label modification requires system-level permissions."); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + System.out.println("LABEL - Creates, changes, or deletes the volume label of a disk."); + System.out.println("\nNote: This is a read-only simulation."); + System.out.println("Actual volume label modification requires system-level permissions."); - if (args.length == 0) { - // Show current drive label - String currentPath = context.getCurrentDir().getAbsolutePath(); - String driveLetter = currentPath.substring(0, Math.min(2, currentPath.length())); - System.out.println("\nVolume in drive " + driveLetter + " has no label."); - System.out.println("Volume label (11 characters, ENTER for none)? "); - } else { - System.out.println("\nSpecified drive: " + args[0]); - System.out.println("Volume label change requires administrator privileges."); - } + if (args.length == 0) { + // Show current drive label + String currentPath = context.getCurrentDir().getAbsolutePath(); + String driveLetter = currentPath.substring(0, Math.min(2, currentPath.length())); + System.out.println("\nVolume in drive " + driveLetter + " has no label."); + System.out.println("Volume label (11 characters, ENTER for none)? "); + } else { + System.out.println("\nSpecified drive: " + args[0]); + System.out.println("Volume label change requires administrator privileges."); } + } - @Override - public String description() { - return "Creates, changes, or deletes the volume label of a disk."; - } + @Override + public String description() { + return "Creates, changes, or deletes the volume label of a disk."; + } - @Override - public String usage() { - return "label [drive:][label]"; - } + @Override + public String usage() { + return "label [drive:][label]"; + } } diff --git a/src/main/java/com/mycmd/commands/LsCommand.java b/src/main/java/com/mycmd/commands/LsCommand.java index e8605f9..bfca1e7 100644 --- a/src/main/java/com/mycmd/commands/LsCommand.java +++ b/src/main/java/com/mycmd/commands/LsCommand.java @@ -8,28 +8,28 @@ /** LsCommand - lists files and directories in the shell's current directory. */ public class LsCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - Path dir = context.getCurrentDir().toPath(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + Path dir = context.getCurrentDir().toPath(); - try (DirectoryStream stream = Files.newDirectoryStream(dir)) { - for (Path path : stream) { - if (Files.isDirectory(path)) { - System.out.println("[DIR] " + path.getFileName()); - } else { - System.out.println(" " + path.getFileName()); - } - } + try (DirectoryStream stream = Files.newDirectoryStream(dir)) { + for (Path path : stream) { + if (Files.isDirectory(path)) { + System.out.println("[DIR] " + path.getFileName()); + } else { + System.out.println(" " + path.getFileName()); } + } } + } - @Override - public String description() { - return "List files and directories in the current directory."; - } + @Override + public String description() { + return "List files and directories in the current directory."; + } - @Override - public String usage() { - return "ls"; - } + @Override + public String usage() { + return "ls"; + } } diff --git a/src/main/java/com/mycmd/commands/MkdirCommand.java b/src/main/java/com/mycmd/commands/MkdirCommand.java index 1530ea7..3b98198 100644 --- a/src/main/java/com/mycmd/commands/MkdirCommand.java +++ b/src/main/java/com/mycmd/commands/MkdirCommand.java @@ -16,29 +16,29 @@ * appropriate feedback for success or failure conditions. */ public class MkdirCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length == 0) { - System.out.println("Usage: " + usage()); - return; - } - File dir = new File(context.getCurrentDir(), args[0]); - if (dir.exists()) { - System.out.println("Directory already exists."); - } else if (dir.mkdirs()) { - System.out.println("Directory created."); - } else { - System.out.println("Failed to create directory."); - } + @Override + public void execute(String[] args, ShellContext context) { + if (args.length == 0) { + System.out.println("Usage: " + usage()); + return; } - - @Override - public String description() { - return "Create a new directory."; + File dir = new File(context.getCurrentDir(), args[0]); + if (dir.exists()) { + System.out.println("Directory already exists."); + } else if (dir.mkdirs()) { + System.out.println("Directory created."); + } else { + System.out.println("Failed to create directory."); } + } - @Override - public String usage() { - return "mkdir "; - } + @Override + public String description() { + return "Create a new directory."; + } + + @Override + public String usage() { + return "mkdir "; + } } diff --git a/src/main/java/com/mycmd/commands/MoreCommand.java b/src/main/java/com/mycmd/commands/MoreCommand.java index e4bde80..895264f 100644 --- a/src/main/java/com/mycmd/commands/MoreCommand.java +++ b/src/main/java/com/mycmd/commands/MoreCommand.java @@ -14,62 +14,62 @@ */ public class MoreCommand implements Command { - private static final int LINES_PER_PAGE = 20; + private static final int LINES_PER_PAGE = 20; - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Displays output one screen at a time."); - System.out.println("\nMORE [/E [/C] [/P] [/S] [/Tn] [+n]] < [drive:][path]filename"); - System.out.println("command-name | MORE [/E [/C] [/P] [/S] [/Tn] [+n]]"); - System.out.println("\nExample: more filename.txt"); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Displays output one screen at a time."); + System.out.println("\nMORE [/E [/C] [/P] [/S] [/Tn] [+n]] < [drive:][path]filename"); + System.out.println("command-name | MORE [/E [/C] [/P] [/S] [/Tn] [+n]]"); + System.out.println("\nExample: more filename.txt"); + return; + } - String filename = args[0]; - java.io.File file = new java.io.File(filename); + String filename = args[0]; + java.io.File file = new java.io.File(filename); - if (!file.isAbsolute()) { - file = new java.io.File(context.getCurrentDir(), filename); - } + if (!file.isAbsolute()) { + file = new java.io.File(context.getCurrentDir(), filename); + } - if (!file.exists()) { - System.out.println("Cannot access " + filename); - return; - } + if (!file.exists()) { + System.out.println("Cannot access " + filename); + return; + } - if (!file.isFile()) { - System.out.println(filename + " is not a file."); - return; - } + if (!file.isFile()) { + System.out.println(filename + " is not a file."); + return; + } - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - int lineCount = 0; + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + int lineCount = 0; - while ((line = reader.readLine()) != null) { - System.out.println(line); - lineCount++; + while ((line = reader.readLine()) != null) { + System.out.println(line); + lineCount++; - if (lineCount % LINES_PER_PAGE == 0) { - System.out.print("-- More -- "); - System.in.read(); // Wait for user input - // Clear the input buffer - while (System.in.available() > 0) { - System.in.read(); - } - } - } + if (lineCount % LINES_PER_PAGE == 0) { + System.out.print("-- More -- "); + System.in.read(); // Wait for user input + // Clear the input buffer + while (System.in.available() > 0) { + System.in.read(); + } } + } } + } - @Override - public String description() { - return "Displays output one screen at a time."; - } + @Override + public String description() { + return "Displays output one screen at a time."; + } - @Override - public String usage() { - return "more [filename]"; - } + @Override + public String usage() { + return "more [filename]"; + } } diff --git a/src/main/java/com/mycmd/commands/MoveCommand.java b/src/main/java/com/mycmd/commands/MoveCommand.java index 05dda9e..0abc563 100644 --- a/src/main/java/com/mycmd/commands/MoveCommand.java +++ b/src/main/java/com/mycmd/commands/MoveCommand.java @@ -19,26 +19,26 @@ * move operation. */ public class MoveCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Usage: " + usage()); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Usage: " + usage()); + return; + } - Path source = context.resolvePath(args[0]).toPath(); - Path destination = context.resolvePath(args[1]).toPath(); + Path source = context.resolvePath(args[0]).toPath(); + Path destination = context.resolvePath(args[1]).toPath(); - if (!Files.exists(source)) { - System.out.println("The system cannot find the file specified."); - return; - } + if (!Files.exists(source)) { + System.out.println("The system cannot find the file specified."); + return; + } - try { - Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING); - System.out.println("Moved: " + source.getFileName() + " -> " + destination); - } catch (IOException e) { - System.out.println("Error moving file: " + e.getMessage()); - } + try { + Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING); + System.out.println("Moved: " + source.getFileName() + " -> " + destination); + } catch (IOException e) { + System.out.println("Error moving file: " + e.getMessage()); } + } } diff --git a/src/main/java/com/mycmd/commands/MsgCommand.java b/src/main/java/com/mycmd/commands/MsgCommand.java index 1998fa3..353e8c3 100644 --- a/src/main/java/com/mycmd/commands/MsgCommand.java +++ b/src/main/java/com/mycmd/commands/MsgCommand.java @@ -11,81 +11,76 @@ */ public class MsgCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Send a message to a user."); - System.out.println("\nMSG {username | sessionname | sessionid | @filename | *}"); - System.out.println(" [/SERVER:servername] [/TIME:seconds] [/V] [/W] [message]"); - System.out.println("\n username Identifies the specified username."); - System.out.println(" sessionname The name of the session."); - System.out.println(" sessionid The ID of the session."); - System.out.println( - " @filename Identifies a file containing a list of usernames."); - System.out.println( - " * Sends message to all sessions on specified server."); - System.out.println(" /SERVER:servername Server to contact (default is current)."); - System.out.println( - " /TIME:seconds Time to wait for receiver to acknowledge msg."); - System.out.println( - " /V Display information about actions being performed."); - System.out.println( - " /W Wait for response from user, useful with /V."); - System.out.println(" message Message to send."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Send a message to a user."); + System.out.println("\nMSG {username | sessionname | sessionid | @filename | *}"); + System.out.println(" [/SERVER:servername] [/TIME:seconds] [/V] [/W] [message]"); + System.out.println("\n username Identifies the specified username."); + System.out.println(" sessionname The name of the session."); + System.out.println(" sessionid The ID of the session."); + System.out.println(" @filename Identifies a file containing a list of usernames."); + System.out.println( + " * Sends message to all sessions on specified server."); + System.out.println(" /SERVER:servername Server to contact (default is current)."); + System.out.println(" /TIME:seconds Time to wait for receiver to acknowledge msg."); + System.out.println( + " /V Display information about actions being performed."); + System.out.println(" /W Wait for response from user, useful with /V."); + System.out.println(" message Message to send."); + return; + } - String os = System.getProperty("os.name").toLowerCase(); + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("MSG command is primarily for Windows systems."); - System.out.println("On Unix-like systems, use 'write' or 'wall' instead."); - return; - } + if (!os.contains("win")) { + System.out.println("MSG command is primarily for Windows systems."); + System.out.println("On Unix-like systems, use 'write' or 'wall' instead."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("msg"); - for (String arg : args) { - if (arg.contains(" ")) { - cmdBuilder.append(" \"").append(arg).append("\""); - } else { - cmdBuilder.append(" ").append(arg); - } - } + try { + StringBuilder cmdBuilder = new StringBuilder("msg"); + for (String arg : args) { + if (arg.contains(" ")) { + cmdBuilder.append(" \"").append(arg).append("\""); + } else { + cmdBuilder.append(" ").append(arg); + } + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - Process process = pb.start(); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + Process process = pb.start(); - java.io.BufferedReader reader = - new java.io.BufferedReader( - new java.io.InputStreamReader(process.getInputStream())); - java.io.BufferedReader errorReader = - new java.io.BufferedReader( - new java.io.InputStreamReader(process.getErrorStream())); + java.io.BufferedReader reader = + new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream())); + java.io.BufferedReader errorReader = + new java.io.BufferedReader(new java.io.InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing msg: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing msg: " + e.getMessage()); } + } - @Override - public String description() { - return "Sends a message to a user."; - } + @Override + public String description() { + return "Sends a message to a user."; + } - @Override - public String usage() { - return "msg username [message]"; - } + @Override + public String usage() { + return "msg username [message]"; + } } diff --git a/src/main/java/com/mycmd/commands/NetCommand.java b/src/main/java/com/mycmd/commands/NetCommand.java index d71e891..17386fc 100644 --- a/src/main/java/com/mycmd/commands/NetCommand.java +++ b/src/main/java/com/mycmd/commands/NetCommand.java @@ -12,76 +12,72 @@ */ public class NetCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("The syntax of this command is:"); - System.out.println("\nNET"); - System.out.println( - " [ ACCOUNTS | COMPUTER | CONFIG | CONTINUE | FILE | GROUP | HELP |"); - System.out.println(" HELPMSG | LOCALGROUP | PAUSE | SESSION | SHARE | START |"); - System.out.println(" STATISTICS | STOP | TIME | USE | USER | VIEW ]"); - System.out.println("\nCommon commands:"); - System.out.println(" NET USER - Displays user account information"); - System.out.println( - " NET USE - Connects/disconnects network resources"); - System.out.println(" NET START - Lists or starts network services"); - System.out.println(" NET STOP - Stops network services"); - System.out.println(" NET SHARE - Displays shared resources"); - System.out.println(" NET SESSION - Lists or disconnects sessions"); - System.out.println("\nNote: Most NET commands require administrator privileges."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("The syntax of this command is:"); + System.out.println("\nNET"); + System.out.println(" [ ACCOUNTS | COMPUTER | CONFIG | CONTINUE | FILE | GROUP | HELP |"); + System.out.println(" HELPMSG | LOCALGROUP | PAUSE | SESSION | SHARE | START |"); + System.out.println(" STATISTICS | STOP | TIME | USE | USER | VIEW ]"); + System.out.println("\nCommon commands:"); + System.out.println(" NET USER - Displays user account information"); + System.out.println(" NET USE - Connects/disconnects network resources"); + System.out.println(" NET START - Lists or starts network services"); + System.out.println(" NET STOP - Stops network services"); + System.out.println(" NET SHARE - Displays shared resources"); + System.out.println(" NET SESSION - Lists or disconnects sessions"); + System.out.println("\nNote: Most NET commands require administrator privileges."); + return; + } - String subCommand = args[0].toLowerCase(); + String subCommand = args[0].toLowerCase(); - try { - StringBuilder cmdBuilder = new StringBuilder("net ").append(subCommand); - for (int i = 1; i < args.length; i++) { - cmdBuilder.append(" ").append(args[i]); - } + try { + StringBuilder cmdBuilder = new StringBuilder("net ").append(subCommand); + for (int i = 1; i < args.length; i++) { + cmdBuilder.append(" ").append(args[i]); + } - ProcessBuilder pb = new ProcessBuilder(); - String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb = new ProcessBuilder(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - pb.command("cmd.exe", "/c", cmdBuilder.toString()); - } else { - System.out.println("NET command is primarily for Windows systems."); - return; - } + if (os.contains("win")) { + pb.command("cmd.exe", "/c", cmdBuilder.toString()); + } else { + System.out.println("NET command is primarily for Windows systems."); + return; + } - Process process = pb.start(); - java.io.BufferedReader reader = - new java.io.BufferedReader( - new java.io.InputStreamReader(process.getInputStream())); - java.io.BufferedReader errorReader = - new java.io.BufferedReader( - new java.io.InputStreamReader(process.getErrorStream())); + Process process = pb.start(); + java.io.BufferedReader reader = + new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream())); + java.io.BufferedReader errorReader = + new java.io.BufferedReader(new java.io.InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing net command: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing net command: " + e.getMessage()); } + } - @Override - public String description() { - return "Network command - manages network resources and connections."; - } + @Override + public String description() { + return "Network command - manages network resources and connections."; + } - @Override - public String usage() { - return "net [user | use | start | stop | share | session] [options]"; - } + @Override + public String usage() { + return "net [user | use | start | stop | share | session] [options]"; + } } diff --git a/src/main/java/com/mycmd/commands/NetshCommand.java b/src/main/java/com/mycmd/commands/NetshCommand.java index 8a3b5d6..b1436f8 100644 --- a/src/main/java/com/mycmd/commands/NetshCommand.java +++ b/src/main/java/com/mycmd/commands/NetshCommand.java @@ -14,64 +14,63 @@ */ public class NetshCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("NETSH is only available on Windows systems."); - return; - } + if (!os.contains("win")) { + System.out.println("NETSH is only available on Windows systems."); + return; + } - if (args.length == 0) { - System.out.println("Network Shell - command-line scripting utility."); - System.out.println("\nCommon commands:"); - System.out.println(" netsh interface show interface"); - System.out.println(" netsh interface ip show config"); - System.out.println(" netsh wlan show profiles"); - System.out.println(" netsh wlan show networks"); - System.out.println(" netsh firewall show state"); - System.out.println("\nNote: Some commands require administrator privileges."); - return; - } + if (args.length == 0) { + System.out.println("Network Shell - command-line scripting utility."); + System.out.println("\nCommon commands:"); + System.out.println(" netsh interface show interface"); + System.out.println(" netsh interface ip show config"); + System.out.println(" netsh wlan show profiles"); + System.out.println(" netsh wlan show networks"); + System.out.println(" netsh firewall show state"); + System.out.println("\nNote: Some commands require administrator privileges."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("netsh"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + StringBuilder cmdBuilder = new StringBuilder("netsh"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - Process process = pb.start(); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing netsh: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing netsh: " + e.getMessage()); } + } - @Override - public String description() { - return "Network Shell - command-line scripting utility for network components."; - } + @Override + public String description() { + return "Network Shell - command-line scripting utility for network components."; + } - @Override - public String usage() { - return "netsh [context] [command]"; - } + @Override + public String usage() { + return "netsh [context] [command]"; + } } diff --git a/src/main/java/com/mycmd/commands/NetstatCommand.java b/src/main/java/com/mycmd/commands/NetstatCommand.java index 7af3f3e..afdc90c 100644 --- a/src/main/java/com/mycmd/commands/NetstatCommand.java +++ b/src/main/java/com/mycmd/commands/NetstatCommand.java @@ -14,46 +14,45 @@ */ public class NetstatCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - try { - StringBuilder cmdBuilder = new StringBuilder("netstat"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } - - ProcessBuilder pb = new ProcessBuilder(); - String os = System.getProperty("os.name").toLowerCase(); - - if (os.contains("win")) { - pb.command("cmd.exe", "/c", cmdBuilder.toString()); - } else { - pb.command("sh", "-c", cmdBuilder.toString()); - } - - Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } - - process.waitFor(); - - } catch (Exception e) { - System.out.println("Error executing netstat: " + e.getMessage()); - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + try { + StringBuilder cmdBuilder = new StringBuilder("netstat"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } + + ProcessBuilder pb = new ProcessBuilder(); + String os = System.getProperty("os.name").toLowerCase(); + + if (os.contains("win")) { + pb.command("cmd.exe", "/c", cmdBuilder.toString()); + } else { + pb.command("sh", "-c", cmdBuilder.toString()); + } + + Process process = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + + process.waitFor(); + + } catch (Exception e) { + System.out.println("Error executing netstat: " + e.getMessage()); } + } - @Override - public String description() { - return "Displays active TCP connections and listening ports."; - } + @Override + public String description() { + return "Displays active TCP connections and listening ports."; + } - @Override - public String usage() { - return "netstat [-a] [-n] [-o] [-p protocol]"; - } + @Override + public String usage() { + return "netstat [-a] [-n] [-o] [-p protocol]"; + } } diff --git a/src/main/java/com/mycmd/commands/NslookupCommand.java b/src/main/java/com/mycmd/commands/NslookupCommand.java index 22be440..843fe72 100644 --- a/src/main/java/com/mycmd/commands/NslookupCommand.java +++ b/src/main/java/com/mycmd/commands/NslookupCommand.java @@ -13,58 +13,57 @@ */ public class NslookupCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Usage: nslookup [hostname|IP]"); - System.out.println("\nQueries DNS to obtain domain name or IP address mapping."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Usage: nslookup [hostname|IP]"); + System.out.println("\nQueries DNS to obtain domain name or IP address mapping."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("nslookup"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + StringBuilder cmdBuilder = new StringBuilder("nslookup"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - ProcessBuilder pb = new ProcessBuilder(); - String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb = new ProcessBuilder(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - pb.command("cmd.exe", "/c", cmdBuilder.toString()); - } else { - pb.command("sh", "-c", cmdBuilder.toString()); - } + if (os.contains("win")) { + pb.command("cmd.exe", "/c", cmdBuilder.toString()); + } else { + pb.command("sh", "-c", cmdBuilder.toString()); + } - Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing nslookup: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing nslookup: " + e.getMessage()); } + } - @Override - public String description() { - return "Queries DNS to obtain domain name or IP address mapping."; - } + @Override + public String description() { + return "Queries DNS to obtain domain name or IP address mapping."; + } - @Override - public String usage() { - return "nslookup [hostname|IP]"; - } + @Override + public String usage() { + return "nslookup [hostname|IP]"; + } } diff --git a/src/main/java/com/mycmd/commands/PathCommand.java b/src/main/java/com/mycmd/commands/PathCommand.java index 9bf8139..bff2c21 100644 --- a/src/main/java/com/mycmd/commands/PathCommand.java +++ b/src/main/java/com/mycmd/commands/PathCommand.java @@ -11,39 +11,39 @@ */ public class PathCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - // Display current PATH - String path = System.getenv("PATH"); - if (path != null) { - System.out.println("PATH=" + path); - } else { - System.out.println("No Path"); - } - return; - } - - System.out.println("Note: Modifying PATH in MyCMD only affects the current shell session."); - System.out.println( - "To permanently modify PATH, use Windows System Properties or setx command."); - - String newPath = String.join(" ", args); - - if (newPath.equalsIgnoreCase(";")) { - System.out.println("PATH cleared (session only)"); - } else { - System.out.println("PATH set to: " + newPath + " (session only)"); - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + // Display current PATH + String path = System.getenv("PATH"); + if (path != null) { + System.out.println("PATH=" + path); + } else { + System.out.println("No Path"); + } + return; } - @Override - public String description() { - return "Displays or sets the command path."; - } + System.out.println("Note: Modifying PATH in MyCMD only affects the current shell session."); + System.out.println( + "To permanently modify PATH, use Windows System Properties or setx command."); + + String newPath = String.join(" ", args); - @Override - public String usage() { - return "path [path]"; + if (newPath.equalsIgnoreCase(";")) { + System.out.println("PATH cleared (session only)"); + } else { + System.out.println("PATH set to: " + newPath + " (session only)"); } + } + + @Override + public String description() { + return "Displays or sets the command path."; + } + + @Override + public String usage() { + return "path [path]"; + } } diff --git a/src/main/java/com/mycmd/commands/PauseCommand.java b/src/main/java/com/mycmd/commands/PauseCommand.java index 120c15b..03ba65a 100644 --- a/src/main/java/com/mycmd/commands/PauseCommand.java +++ b/src/main/java/com/mycmd/commands/PauseCommand.java @@ -4,34 +4,33 @@ import com.mycmd.ShellContext; public class PauseCommand implements Command { - /** - * Execute the pause command. - * - *

Prints "Press Enter to continue..." and waits for the user to press Enter before - * continuing. - * - *

If an exception occurs during the pause, it is ignored. - * - * @param args The arguments to the command. - * @param context The context of the shell. - */ - @Override - public void execute(String[] args, ShellContext context) { - System.out.println("Press Enter to continue..."); - try { - System.in.read(); - } catch (Exception e) { - // Ignore exceptions during pause - } + /** + * Execute the pause command. + * + *

Prints "Press Enter to continue..." and waits for the user to press Enter before continuing. + * + *

If an exception occurs during the pause, it is ignored. + * + * @param args The arguments to the command. + * @param context The context of the shell. + */ + @Override + public void execute(String[] args, ShellContext context) { + System.out.println("Press Enter to continue..."); + try { + System.in.read(); + } catch (Exception e) { + // Ignore exceptions during pause } + } - @Override - public String description() { - return "Pause execution until user presses Enter."; - } + @Override + public String description() { + return "Pause execution until user presses Enter."; + } - @Override - public String usage() { - return "pause"; - } + @Override + public String usage() { + return "pause"; + } } diff --git a/src/main/java/com/mycmd/commands/PingCommand.java b/src/main/java/com/mycmd/commands/PingCommand.java index 36fb42d..7e892b6 100644 --- a/src/main/java/com/mycmd/commands/PingCommand.java +++ b/src/main/java/com/mycmd/commands/PingCommand.java @@ -52,372 +52,358 @@ */ public class PingCommand implements Command { - private static final Pattern TIME_PATTERN_WINDOWS = - Pattern.compile("time[=<]\\s*(\\d+)\\s*ms", Pattern.CASE_INSENSITIVE); - private static final Pattern TIME_PATTERN_UNIX = - Pattern.compile("time=(\\d+\\.?\\d*)\\s*ms", Pattern.CASE_INSENSITIVE); - - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - displayHelp(); - return; - } - - String host = args[0]; - - // Validate hostname/IP - if (!validateHost(host)) { - System.out.println( - "Ping request could not find host " - + host - + ". Please check the name and try again."); - return; - } - - // Resolve hostname to IP - String resolvedIP = resolveHost(host); - if (resolvedIP == null) { - System.out.println( - "Ping request could not find host " - + host - + ". Please check the name and try again."); - return; - } + private static final Pattern TIME_PATTERN_WINDOWS = + Pattern.compile("time[=<]\\s*(\\d+)\\s*ms", Pattern.CASE_INSENSITIVE); + private static final Pattern TIME_PATTERN_UNIX = + Pattern.compile("time=(\\d+\\.?\\d*)\\s*ms", Pattern.CASE_INSENSITIVE); + + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + displayHelp(); + return; + } - // Build ping command based on operating system - String[] command = buildPingCommand(host, args); + String host = args[0]; - try { - executePing(command, host, resolvedIP); - } catch (InterruptedException e) { - System.out.println("\nPing command was interrupted."); - Thread.currentThread().interrupt(); - } + // Validate hostname/IP + if (!validateHost(host)) { + System.out.println( + "Ping request could not find host " + host + ". Please check the name and try again."); + return; } - /** Displays usage help for the ping command. */ - private void displayHelp() { - String os = System.getProperty("os.name").toLowerCase(); - - System.out.println("\nUsage: ping [-t] [-n count] [-l size] [-w timeout] target_name\n"); - System.out.println("Options:"); - System.out.println(" -t Ping the specified host until stopped."); - System.out.println(" To stop - press Control-C."); - System.out.println(" -n count Number of echo requests to send (default: 4)."); - - if (os.contains("win")) { - System.out.println(" -l size Send buffer size (default: 32 bytes)."); - System.out.println( - " -w timeout Timeout in milliseconds to wait for each reply."); - } else { - System.out.println(" -c count Number of echo requests to send (Unix-style)."); - System.out.println( - " -i interval Wait interval seconds between sending each packet."); - } - - System.out.println("\nExamples:"); - System.out.println(" ping google.com"); - System.out.println(" ping 8.8.8.8"); - System.out.println(" ping google.com -n 10"); - System.out.println(" ping 1.1.1.1 -t"); + // Resolve hostname to IP + String resolvedIP = resolveHost(host); + if (resolvedIP == null) { + System.out.println( + "Ping request could not find host " + host + ". Please check the name and try again."); + return; } - /** Validates if the host string is a valid hostname or IP address format. */ - private boolean validateHost(String host) { - if (host == null || host.trim().isEmpty()) { - return false; - } + // Build ping command based on operating system + String[] command = buildPingCommand(host, args); - // Basic validation - allow alphanumeric, dots, hyphens for hostnames - // More complex validation will happen during resolution - return host.matches("^[a-zA-Z0-9.-]+$"); + try { + executePing(command, host, resolvedIP); + } catch (InterruptedException e) { + System.out.println("\nPing command was interrupted."); + Thread.currentThread().interrupt(); + } + } + + /** Displays usage help for the ping command. */ + private void displayHelp() { + String os = System.getProperty("os.name").toLowerCase(); + + System.out.println("\nUsage: ping [-t] [-n count] [-l size] [-w timeout] target_name\n"); + System.out.println("Options:"); + System.out.println(" -t Ping the specified host until stopped."); + System.out.println(" To stop - press Control-C."); + System.out.println(" -n count Number of echo requests to send (default: 4)."); + + if (os.contains("win")) { + System.out.println(" -l size Send buffer size (default: 32 bytes)."); + System.out.println(" -w timeout Timeout in milliseconds to wait for each reply."); + } else { + System.out.println(" -c count Number of echo requests to send (Unix-style)."); + System.out.println(" -i interval Wait interval seconds between sending each packet."); } - /** Resolves hostname to IP address. */ - private String resolveHost(String host) { - try { - InetAddress address = InetAddress.getByName(host); - return address.getHostAddress(); - } catch (UnknownHostException e) { - return null; - } + System.out.println("\nExamples:"); + System.out.println(" ping google.com"); + System.out.println(" ping 8.8.8.8"); + System.out.println(" ping google.com -n 10"); + System.out.println(" ping 1.1.1.1 -t"); + } + + /** Validates if the host string is a valid hostname or IP address format. */ + private boolean validateHost(String host) { + if (host == null || host.trim().isEmpty()) { + return false; } - /** Executes the ping command and displays results with statistics. */ - private void executePing(String[] command, String host, String resolvedIP) - throws IOException, InterruptedException { + // Basic validation - allow alphanumeric, dots, hyphens for hostnames + // More complex validation will happen during resolution + return host.matches("^[a-zA-Z0-9.-]+$"); + } + + /** Resolves hostname to IP address. */ + private String resolveHost(String host) { + try { + InetAddress address = InetAddress.getByName(host); + return address.getHostAddress(); + } catch (UnknownHostException e) { + return null; + } + } - String os = System.getProperty("os.name").toLowerCase(); + /** Executes the ping command and displays results with statistics. */ + private void executePing(String[] command, String host, String resolvedIP) + throws IOException, InterruptedException { - // Display initial message - System.out.println("\nPinging " + host + " [" + resolvedIP + "] with 32 bytes of data:"); + String os = System.getProperty("os.name").toLowerCase(); - ProcessBuilder pb = new ProcessBuilder(command); - Process process = pb.start(); + // Display initial message + System.out.println("\nPinging " + host + " [" + resolvedIP + "] with 32 bytes of data:"); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + ProcessBuilder pb = new ProcessBuilder(command); + Process process = pb.start(); - // Statistics tracking - PingStatistics stats = new PingStatistics(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - boolean statsSection = false; + // Statistics tracking + PingStatistics stats = new PingStatistics(); - // Read and display output in real-time - while ((line = reader.readLine()) != null) { - System.out.println(line); + String line; + boolean statsSection = false; - // Parse statistics from output - if (line.contains("Packets: Sent") || line.contains("packets transmitted")) { - statsSection = true; - } + // Read and display output in real-time + while ((line = reader.readLine()) != null) { + System.out.println(line); - // Extract time values for custom statistics - if (!statsSection) { - extractTimeFromLine(line, stats, os); - } - } + // Parse statistics from output + if (line.contains("Packets: Sent") || line.contains("packets transmitted")) { + statsSection = true; + } - // Display error output if any - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + // Extract time values for custom statistics + if (!statsSection) { + extractTimeFromLine(line, stats, os); + } + } - int exitCode = process.waitFor(); + // Display error output if any + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - // If statistics weren't displayed by the native command, show custom stats - if (!statsSection && stats.received > 0) { - displayCustomStatistics(stats, resolvedIP); - } + int exitCode = process.waitFor(); - if (exitCode != 0 && stats.received == 0) { - System.out.println("\nPing command failed. Host may be unreachable."); - } + // If statistics weren't displayed by the native command, show custom stats + if (!statsSection && stats.received > 0) { + displayCustomStatistics(stats, resolvedIP); } - /** Extracts time values from ping output lines for statistics. */ - private void extractTimeFromLine(String line, PingStatistics stats, String os) { - Pattern pattern = os.contains("win") ? TIME_PATTERN_WINDOWS : TIME_PATTERN_UNIX; - Matcher matcher = pattern.matcher(line); - - if (matcher.find()) { - try { - double time = Double.parseDouble(matcher.group(1)); - stats.addTime(time); - } catch (NumberFormatException e) { - // Ignore parsing errors - } - } - - // Count sent/received packets - if (line.toLowerCase().contains("reply from") - || line.toLowerCase().contains("bytes from")) { - stats.received++; - stats.sent++; - } else if (line.toLowerCase().contains("request timed out") - || line.toLowerCase().contains("destination host unreachable")) { - stats.sent++; - stats.lost++; - } + if (exitCode != 0 && stats.received == 0) { + System.out.println("\nPing command failed. Host may be unreachable."); + } + } + + /** Extracts time values from ping output lines for statistics. */ + private void extractTimeFromLine(String line, PingStatistics stats, String os) { + Pattern pattern = os.contains("win") ? TIME_PATTERN_WINDOWS : TIME_PATTERN_UNIX; + Matcher matcher = pattern.matcher(line); + + if (matcher.find()) { + try { + double time = Double.parseDouble(matcher.group(1)); + stats.addTime(time); + } catch (NumberFormatException e) { + // Ignore parsing errors + } } - /** Displays custom ping statistics when native command doesn't provide them. */ - private void displayCustomStatistics(PingStatistics stats, String ip) { - System.out.println("\nPing statistics for " + ip + ":"); - System.out.println( - " Packets: Sent = " - + stats.sent - + ", Received = " - + stats.received - + ", Lost = " - + stats.lost - + " (" - + stats.getLossPercentage() - + "% loss),"); - - if (stats.received > 0) { - System.out.println("Approximate round trip times in milli-seconds:"); - System.out.println( - " Minimum = " - + String.format("%.0f", stats.minTime) - + "ms" - + ", Maximum = " - + String.format("%.0f", stats.maxTime) - + "ms" - + ", Average = " - + String.format("%.0f", stats.getAverageTime()) - + "ms"); - } + // Count sent/received packets + if (line.toLowerCase().contains("reply from") || line.toLowerCase().contains("bytes from")) { + stats.received++; + stats.sent++; + } else if (line.toLowerCase().contains("request timed out") + || line.toLowerCase().contains("destination host unreachable")) { + stats.sent++; + stats.lost++; + } + } + + /** Displays custom ping statistics when native command doesn't provide them. */ + private void displayCustomStatistics(PingStatistics stats, String ip) { + System.out.println("\nPing statistics for " + ip + ":"); + System.out.println( + " Packets: Sent = " + + stats.sent + + ", Received = " + + stats.received + + ", Lost = " + + stats.lost + + " (" + + stats.getLossPercentage() + + "% loss),"); + + if (stats.received > 0) { + System.out.println("Approximate round trip times in milli-seconds:"); + System.out.println( + " Minimum = " + + String.format("%.0f", stats.minTime) + + "ms" + + ", Maximum = " + + String.format("%.0f", stats.maxTime) + + "ms" + + ", Average = " + + String.format("%.0f", stats.getAverageTime()) + + "ms"); } + } - /** Builds the appropriate ping command based on the operating system and arguments. */ - private String[] buildPingCommand(String host, String[] args) { - String os = System.getProperty("os.name").toLowerCase(); + /** Builds the appropriate ping command based on the operating system and arguments. */ + private String[] buildPingCommand(String host, String[] args) { + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - return buildWindowsPingCommand(host, args); - } else { - return buildUnixPingCommand(host, args); - } + if (os.contains("win")) { + return buildWindowsPingCommand(host, args); + } else { + return buildUnixPingCommand(host, args); } + } - /** Builds ping command for Windows systems. */ - private String[] buildWindowsPingCommand(String host, String[] args) { - List command = new ArrayList<>(); - command.add("ping"); - - boolean continuous = false; - Integer count = null; - Integer timeout = null; - Integer bufferSize = null; - - // Parse arguments - for (int i = 1; i < args.length; i++) { - String arg = args[i].toLowerCase(); - - if ("-t".equals(arg)) { - continuous = true; - } else if (("-n".equals(arg) || "-c".equals(arg)) && i + 1 < args.length) { - try { - count = Integer.parseInt(args[i + 1]); - i++; // Skip next argument - } catch (NumberFormatException e) { - System.out.println( - "Warning: Invalid count value '" - + args[i + 1] - + "', using default (4)"); - } - } else if ("-w".equals(arg) && i + 1 < args.length) { - try { - timeout = Integer.parseInt(args[i + 1]); - i++; // Skip next argument - } catch (NumberFormatException e) { - System.out.println( - "Warning: Invalid timeout value '" + args[i + 1] + "', using default"); - } - } else if ("-l".equals(arg) && i + 1 < args.length) { - try { - bufferSize = Integer.parseInt(args[i + 1]); - i++; // Skip next argument - } catch (NumberFormatException e) { - System.out.println( - "Warning: Invalid buffer size '" - + args[i + 1] - + "', using default (32)"); - } - } - } + /** Builds ping command for Windows systems. */ + private String[] buildWindowsPingCommand(String host, String[] args) { + List command = new ArrayList<>(); + command.add("ping"); - // Add options to command - if (continuous) { - command.add("-t"); - } else if (count != null && count > 0) { - command.add("-n"); - command.add(String.valueOf(count)); - } else { - command.add("-n"); - command.add("4"); // Default count - } + boolean continuous = false; + Integer count = null; + Integer timeout = null; + Integer bufferSize = null; - if (timeout != null && timeout > 0) { - command.add("-w"); - command.add(String.valueOf(timeout)); - } + // Parse arguments + for (int i = 1; i < args.length; i++) { + String arg = args[i].toLowerCase(); - if (bufferSize != null && bufferSize > 0) { - command.add("-l"); - command.add(String.valueOf(bufferSize)); + if ("-t".equals(arg)) { + continuous = true; + } else if (("-n".equals(arg) || "-c".equals(arg)) && i + 1 < args.length) { + try { + count = Integer.parseInt(args[i + 1]); + i++; // Skip next argument + } catch (NumberFormatException e) { + System.out.println( + "Warning: Invalid count value '" + args[i + 1] + "', using default (4)"); + } + } else if ("-w".equals(arg) && i + 1 < args.length) { + try { + timeout = Integer.parseInt(args[i + 1]); + i++; // Skip next argument + } catch (NumberFormatException e) { + System.out.println("Warning: Invalid timeout value '" + args[i + 1] + "', using default"); } + } else if ("-l".equals(arg) && i + 1 < args.length) { + try { + bufferSize = Integer.parseInt(args[i + 1]); + i++; // Skip next argument + } catch (NumberFormatException e) { + System.out.println( + "Warning: Invalid buffer size '" + args[i + 1] + "', using default (32)"); + } + } + } - command.add(host); - return command.toArray(new String[0]); + // Add options to command + if (continuous) { + command.add("-t"); + } else if (count != null && count > 0) { + command.add("-n"); + command.add(String.valueOf(count)); + } else { + command.add("-n"); + command.add("4"); // Default count } - /** Builds ping command for Unix-like systems (Linux, macOS). */ - private String[] buildUnixPingCommand(String host, String[] args) { - List command = new ArrayList<>(); - command.add("ping"); - - boolean continuous = false; - Integer count = null; - Integer interval = null; - - // Parse arguments - for (int i = 1; i < args.length; i++) { - String arg = args[i].toLowerCase(); - - if ("-t".equals(arg)) { - continuous = true; - } else if (("-n".equals(arg) || "-c".equals(arg)) && i + 1 < args.length) { - try { - count = Integer.parseInt(args[i + 1]); - i++; // Skip next argument - } catch (NumberFormatException e) { - System.out.println( - "Warning: Invalid count value '" - + args[i + 1] - + "', using default (4)"); - } - } else if ("-i".equals(arg) && i + 1 < args.length) { - try { - interval = Integer.parseInt(args[i + 1]); - i++; // Skip next argument - } catch (NumberFormatException e) { - System.out.println( - "Warning: Invalid interval value '" + args[i + 1] + "', using default"); - } - } - } + if (timeout != null && timeout > 0) { + command.add("-w"); + command.add(String.valueOf(timeout)); + } - // Add options to command - if (!continuous) { - command.add("-c"); - command.add(count != null && count > 0 ? String.valueOf(count) : "4"); - } + if (bufferSize != null && bufferSize > 0) { + command.add("-l"); + command.add(String.valueOf(bufferSize)); + } - if (interval != null && interval > 0) { - command.add("-i"); - command.add(String.valueOf(interval)); - } + command.add(host); + return command.toArray(new String[0]); + } + + /** Builds ping command for Unix-like systems (Linux, macOS). */ + private String[] buildUnixPingCommand(String host, String[] args) { + List command = new ArrayList<>(); + command.add("ping"); + + boolean continuous = false; + Integer count = null; + Integer interval = null; + + // Parse arguments + for (int i = 1; i < args.length; i++) { + String arg = args[i].toLowerCase(); - command.add(host); - return command.toArray(new String[0]); + if ("-t".equals(arg)) { + continuous = true; + } else if (("-n".equals(arg) || "-c".equals(arg)) && i + 1 < args.length) { + try { + count = Integer.parseInt(args[i + 1]); + i++; // Skip next argument + } catch (NumberFormatException e) { + System.out.println( + "Warning: Invalid count value '" + args[i + 1] + "', using default (4)"); + } + } else if ("-i".equals(arg) && i + 1 < args.length) { + try { + interval = Integer.parseInt(args[i + 1]); + i++; // Skip next argument + } catch (NumberFormatException e) { + System.out.println( + "Warning: Invalid interval value '" + args[i + 1] + "', using default"); + } + } } - @Override - public String description() { - return "Tests network connectivity to a hostname or IP address."; + // Add options to command + if (!continuous) { + command.add("-c"); + command.add(count != null && count > 0 ? String.valueOf(count) : "4"); } - @Override - public String usage() { - return "ping [-t] [-n count] [-w timeout] [-l size] "; + if (interval != null && interval > 0) { + command.add("-i"); + command.add(String.valueOf(interval)); } - /** Helper class to track ping statistics. */ - private static class PingStatistics { - int sent = 0; - int received = 0; - int lost = 0; - double minTime = Double.MAX_VALUE; - double maxTime = 0; - double totalTime = 0; - - void addTime(double time) { - if (time < minTime) minTime = time; - if (time > maxTime) maxTime = time; - totalTime += time; - } + command.add(host); + return command.toArray(new String[0]); + } + + @Override + public String description() { + return "Tests network connectivity to a hostname or IP address."; + } + + @Override + public String usage() { + return "ping [-t] [-n count] [-w timeout] [-l size] "; + } + + /** Helper class to track ping statistics. */ + private static class PingStatistics { + int sent = 0; + int received = 0; + int lost = 0; + double minTime = Double.MAX_VALUE; + double maxTime = 0; + double totalTime = 0; + + void addTime(double time) { + if (time < minTime) minTime = time; + if (time > maxTime) maxTime = time; + totalTime += time; + } - double getAverageTime() { - return received > 0 ? totalTime / received : 0; - } + double getAverageTime() { + return received > 0 ? totalTime / received : 0; + } - int getLossPercentage() { - return sent > 0 ? (lost * 100) / sent : 0; - } + int getLossPercentage() { + return sent > 0 ? (lost * 100) / sent : 0; } + } } diff --git a/src/main/java/com/mycmd/commands/PwdCommand.java b/src/main/java/com/mycmd/commands/PwdCommand.java index dc0c721..df874b2 100644 --- a/src/main/java/com/mycmd/commands/PwdCommand.java +++ b/src/main/java/com/mycmd/commands/PwdCommand.java @@ -16,18 +16,18 @@ * scripts and when you need to know your exact location in the file system. */ public class PwdCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - System.out.println(context.getCurrentDir().getAbsolutePath()); - } + @Override + public void execute(String[] args, ShellContext context) { + System.out.println(context.getCurrentDir().getAbsolutePath()); + } - @Override - public String description() { - return "Print the current working directory path."; - } + @Override + public String description() { + return "Print the current working directory path."; + } - @Override - public String usage() { - return "pwd"; - } + @Override + public String usage() { + return "pwd"; + } } diff --git a/src/main/java/com/mycmd/commands/RemCommand.java b/src/main/java/com/mycmd/commands/RemCommand.java index 1281997..082442e 100644 --- a/src/main/java/com/mycmd/commands/RemCommand.java +++ b/src/main/java/com/mycmd/commands/RemCommand.java @@ -11,19 +11,19 @@ */ public class RemCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - // REM command does nothing - it's just for comments - // Silently ignore the comment - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + // REM command does nothing - it's just for comments + // Silently ignore the comment + } - @Override - public String description() { - return "Records comments (remarks) in batch files or scripts."; - } + @Override + public String description() { + return "Records comments (remarks) in batch files or scripts."; + } - @Override - public String usage() { - return "rem [comment]"; - } + @Override + public String usage() { + return "rem [comment]"; + } } diff --git a/src/main/java/com/mycmd/commands/RenameCommand.java b/src/main/java/com/mycmd/commands/RenameCommand.java index bfcdb13..98126a9 100644 --- a/src/main/java/com/mycmd/commands/RenameCommand.java +++ b/src/main/java/com/mycmd/commands/RenameCommand.java @@ -10,37 +10,36 @@ /** Implements the "rename" (or "ren") command for MyCMD. Usage: rename */ public class RenameCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length != 2) { - System.out.println("Usage: " + usage()); - return; - } - - File oldFile = context.resolvePath(args[0]); - File newFile = context.resolvePath(args[1]); - - if (!oldFile.exists()) { - System.out.println("The system cannot find the file specified: " + args[0]); - return; - } - - try { - Files.move(oldFile.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - System.out.println( - "File renamed from " + oldFile.getName() + " to " + newFile.getName()); - } catch (IOException e) { - throw new IOException("Failed to rename file: " + e.getMessage(), e); - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length != 2) { + System.out.println("Usage: " + usage()); + return; } - @Override - public String description() { - return "Renames a file or directory."; + File oldFile = context.resolvePath(args[0]); + File newFile = context.resolvePath(args[1]); + + if (!oldFile.exists()) { + System.out.println("The system cannot find the file specified: " + args[0]); + return; } - @Override - public String usage() { - return "rename "; + try { + Files.move(oldFile.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + System.out.println("File renamed from " + oldFile.getName() + " to " + newFile.getName()); + } catch (IOException e) { + throw new IOException("Failed to rename file: " + e.getMessage(), e); } + } + + @Override + public String description() { + return "Renames a file or directory."; + } + + @Override + public String usage() { + return "rename "; + } } diff --git a/src/main/java/com/mycmd/commands/ReplaceCommand.java b/src/main/java/com/mycmd/commands/ReplaceCommand.java index 2acc681..adecba4 100644 --- a/src/main/java/com/mycmd/commands/ReplaceCommand.java +++ b/src/main/java/com/mycmd/commands/ReplaceCommand.java @@ -11,41 +11,39 @@ */ public class ReplaceCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Replaces files."); - System.out.println( - "\nREPLACE [drive1:][path1]filename [drive2:][path2] [/A] [/P] [/R] [/W]"); - System.out.println( - "REPLACE [drive1:][path1]filename [drive2:][path2] [/P] [/R] [/S] [/W] [/U]"); - System.out.println("\n [drive1:][path1]filename Specifies the source file or files."); - System.out.println(" [drive2:][path2] Specifies the directory where files"); - System.out.println(" are to be replaced."); - System.out.println( - " /A Adds new files to destination directory."); - System.out.println(" /P Prompts for confirmation."); - System.out.println(" /R Replaces read-only files as well."); - System.out.println(" /S Replaces files in all subdirectories."); - System.out.println(" /W Waits for you to insert a disk."); - System.out.println(" /U Replaces only files that are older."); - return; - } - - System.out.println("REPLACE command simulation."); - System.out.println( - "This is a simplified version. Use COPY or XCOPY for similar functionality."); - System.out.println("Source: " + args[0]); - System.out.println("Destination: " + args[1]); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Replaces files."); + System.out.println("\nREPLACE [drive1:][path1]filename [drive2:][path2] [/A] [/P] [/R] [/W]"); + System.out.println( + "REPLACE [drive1:][path1]filename [drive2:][path2] [/P] [/R] [/S] [/W] [/U]"); + System.out.println("\n [drive1:][path1]filename Specifies the source file or files."); + System.out.println(" [drive2:][path2] Specifies the directory where files"); + System.out.println(" are to be replaced."); + System.out.println(" /A Adds new files to destination directory."); + System.out.println(" /P Prompts for confirmation."); + System.out.println(" /R Replaces read-only files as well."); + System.out.println(" /S Replaces files in all subdirectories."); + System.out.println(" /W Waits for you to insert a disk."); + System.out.println(" /U Replaces only files that are older."); + return; } - @Override - public String description() { - return "Replaces files in a directory."; - } + System.out.println("REPLACE command simulation."); + System.out.println( + "This is a simplified version. Use COPY or XCOPY for similar functionality."); + System.out.println("Source: " + args[0]); + System.out.println("Destination: " + args[1]); + } - @Override - public String usage() { - return "replace [source] [destination] [/A] [/P] [/R] [/S]"; - } + @Override + public String description() { + return "Replaces files in a directory."; + } + + @Override + public String usage() { + return "replace [source] [destination] [/A] [/P] [/R] [/S]"; + } } diff --git a/src/main/java/com/mycmd/commands/RmdirCommand.java b/src/main/java/com/mycmd/commands/RmdirCommand.java index 106b636..775c860 100644 --- a/src/main/java/com/mycmd/commands/RmdirCommand.java +++ b/src/main/java/com/mycmd/commands/RmdirCommand.java @@ -17,31 +17,31 @@ * directory before deletion - Provides clear error messages for each failure condition */ public class RmdirCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length == 0) { - System.out.println("Usage: " + usage()); - return; - } - File dir = new File(context.getCurrentDir(), args[0]); - if (!dir.exists() || !dir.isDirectory()) { - System.out.println("Directory not found."); - } else if (dir.list().length > 0) { - System.out.println("Directory is not empty."); - } else if (dir.delete()) { - System.out.println("Directory deleted."); - } else { - System.out.println("Failed to delete directory."); - } + @Override + public void execute(String[] args, ShellContext context) { + if (args.length == 0) { + System.out.println("Usage: " + usage()); + return; } - - @Override - public String description() { - return "Remove an empty directory."; + File dir = new File(context.getCurrentDir(), args[0]); + if (!dir.exists() || !dir.isDirectory()) { + System.out.println("Directory not found."); + } else if (dir.list().length > 0) { + System.out.println("Directory is not empty."); + } else if (dir.delete()) { + System.out.println("Directory deleted."); + } else { + System.out.println("Failed to delete directory."); } + } - @Override - public String usage() { - return "rmdir "; - } + @Override + public String description() { + return "Remove an empty directory."; + } + + @Override + public String usage() { + return "rmdir "; + } } diff --git a/src/main/java/com/mycmd/commands/RobocopyCommand.java b/src/main/java/com/mycmd/commands/RobocopyCommand.java index 03e5082..564261e 100644 --- a/src/main/java/com/mycmd/commands/RobocopyCommand.java +++ b/src/main/java/com/mycmd/commands/RobocopyCommand.java @@ -13,68 +13,65 @@ */ public class RobocopyCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("ROBOCOPY :: Robust File Copy"); - System.out.println( - "\nUsage: robocopy [[ ...]] []"); - System.out.println("\nCommon Options:"); - System.out.println(" /S Copy subdirectories (excluding empty ones)"); - System.out.println(" /E Copy subdirectories (including empty ones)"); - System.out.println(" /MIR Mirror a directory tree"); - System.out.println( - " /PURGE Delete dest files/dirs that no longer exist in source"); - System.out.println(" /COPYALL Copy all file info"); - System.out.println(" /R:n Number of retries on failed copies"); - System.out.println(" /W:n Wait time between retries"); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("ROBOCOPY :: Robust File Copy"); + System.out.println("\nUsage: robocopy [[ ...]] []"); + System.out.println("\nCommon Options:"); + System.out.println(" /S Copy subdirectories (excluding empty ones)"); + System.out.println(" /E Copy subdirectories (including empty ones)"); + System.out.println(" /MIR Mirror a directory tree"); + System.out.println(" /PURGE Delete dest files/dirs that no longer exist in source"); + System.out.println(" /COPYALL Copy all file info"); + System.out.println(" /R:n Number of retries on failed copies"); + System.out.println(" /W:n Wait time between retries"); + return; + } - String os = System.getProperty("os.name").toLowerCase(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - try { - StringBuilder cmdBuilder = new StringBuilder("robocopy"); - for (String arg : args) { - cmdBuilder.append(" \"").append(arg).append("\""); - } + if (os.contains("win")) { + try { + StringBuilder cmdBuilder = new StringBuilder("robocopy"); + for (String arg : args) { + cmdBuilder.append(" \"").append(arg).append("\""); + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - pb.directory(context.getCurrentDir()); - Process process = pb.start(); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + pb.directory(context.getCurrentDir()); + Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing robocopy: " + e.getMessage()); - } - } else { - System.out.println("ROBOCOPY is not available on this system. Use 'rsync' instead."); - } + } catch (Exception e) { + System.out.println("Error executing robocopy: " + e.getMessage()); + } + } else { + System.out.println("ROBOCOPY is not available on this system. Use 'rsync' instead."); } + } - @Override - public String description() { - return "Robust File Copy - Advanced file copy utility."; - } + @Override + public String description() { + return "Robust File Copy - Advanced file copy utility."; + } - @Override - public String usage() { - return "robocopy [/S] [/E] [/MIR]"; - } + @Override + public String usage() { + return "robocopy [/S] [/E] [/MIR]"; + } } diff --git a/src/main/java/com/mycmd/commands/RouteCommand.java b/src/main/java/com/mycmd/commands/RouteCommand.java index 859457d..237df7d 100644 --- a/src/main/java/com/mycmd/commands/RouteCommand.java +++ b/src/main/java/com/mycmd/commands/RouteCommand.java @@ -13,68 +13,65 @@ */ public class RouteCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Manipulates network routing tables."); - System.out.println( - "\nROUTE [-f] [-p] [command [destination] [MASK netmask] [gateway]]"); - System.out.println( - "\n -f Clears the routing tables of all gateway entries."); - System.out.println(" -p Makes a route persistent across boots."); - System.out.println(" command One of these:"); - System.out.println(" PRINT Prints a route"); - System.out.println(" ADD Adds a route"); - System.out.println(" DELETE Deletes a route"); - System.out.println(" CHANGE Modifies an existing route"); - System.out.println("\nNote: Administrator privileges required for modification."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Manipulates network routing tables."); + System.out.println("\nROUTE [-f] [-p] [command [destination] [MASK netmask] [gateway]]"); + System.out.println("\n -f Clears the routing tables of all gateway entries."); + System.out.println(" -p Makes a route persistent across boots."); + System.out.println(" command One of these:"); + System.out.println(" PRINT Prints a route"); + System.out.println(" ADD Adds a route"); + System.out.println(" DELETE Deletes a route"); + System.out.println(" CHANGE Modifies an existing route"); + System.out.println("\nNote: Administrator privileges required for modification."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("route"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + StringBuilder cmdBuilder = new StringBuilder("route"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - ProcessBuilder pb = new ProcessBuilder(); - String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb = new ProcessBuilder(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - pb.command("cmd.exe", "/c", cmdBuilder.toString()); - } else { - pb.command("sh", "-c", cmdBuilder.toString()); - } + if (os.contains("win")) { + pb.command("cmd.exe", "/c", cmdBuilder.toString()); + } else { + pb.command("sh", "-c", cmdBuilder.toString()); + } - Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing route: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing route: " + e.getMessage()); } + } - @Override - public String description() { - return "Displays and modifies entries in the local IP routing table."; - } + @Override + public String description() { + return "Displays and modifies entries in the local IP routing table."; + } - @Override - public String usage() { - return "route [print | add | delete | change] [options]"; - } + @Override + public String usage() { + return "route [print | add | delete | change] [options]"; + } } diff --git a/src/main/java/com/mycmd/commands/SearchHistoryCommand.java b/src/main/java/com/mycmd/commands/SearchHistoryCommand.java index e0542e6..a5044bb 100644 --- a/src/main/java/com/mycmd/commands/SearchHistoryCommand.java +++ b/src/main/java/com/mycmd/commands/SearchHistoryCommand.java @@ -5,110 +5,107 @@ import java.util.List; /** - * Command to search through command history. - * Usage: searchhistory [search_term] - * - * If no search term is provided, shows all history. - * If search term is provided, filters history to matching commands. + * Command to search through command history. Usage: searchhistory [search_term] + * + *

If no search term is provided, shows all history. If search term is provided, filters history + * to matching commands. */ public class SearchHistoryCommand implements Command { - - @Override - public void execute(String[] args, ShellContext context) { - List history = context.getHistory(); - - if (history.isEmpty()) { - System.out.println("No command history available."); - return; - } - - // If no search term provided, show all history - if (args.length == 0) { - System.out.println("Command History (use 'searchhistory ' to filter):"); - displayHistory(history, null); - return; - } - - // Join all args as the search term (supports multi-word searches) - String searchTerm = String.join(" ", args).toLowerCase(); - - System.out.println("Searching history for: '" + searchTerm + "'"); - System.out.println(); - - // Filter history - List matches = history.stream() - .filter(cmd -> cmd.toLowerCase().contains(searchTerm)) - .toList(); - - if (matches.isEmpty()) { - System.out.println("No matching commands found."); - System.out.println("Tip: Search is case-insensitive and matches partial text."); - } else { - displayHistory(matches, searchTerm); - System.out.println(); - System.out.println("Found " + matches.size() + " matching command(s)."); - } + + @Override + public void execute(String[] args, ShellContext context) { + List history = context.getHistory(); + + if (history.isEmpty()) { + System.out.println("No command history available."); + return; } - - /** - * Display history entries with line numbers. - * Optionally highlights the search term if provided. - */ - private void displayHistory(List commands, String searchTerm) { - int maxDigits = String.valueOf(commands.size()).length(); - - for (int i = 0; i < commands.size(); i++) { - String lineNum = String.format("%" + maxDigits + "d", i + 1); - String command = commands.get(i); - - // Highlight search term if provided (simple uppercase for visibility) - if (searchTerm != null && !searchTerm.isEmpty()) { - command = highlightTerm(command, searchTerm); - } - - System.out.println(" " + lineNum + " " + command); - } + + // If no search term provided, show all history + if (args.length == 0) { + System.out.println("Command History (use 'searchhistory ' to filter):"); + displayHistory(history, null); + return; } - - /** - * Simple highlighting by surrounding the search term with markers. - * For terminal with color support, you could use ANSI codes instead. - */ - private String highlightTerm(String text, String term) { - // Case-insensitive highlight - int index = text.toLowerCase().indexOf(term.toLowerCase()); - if (index == -1) { - return text; - } - - StringBuilder result = new StringBuilder(); - int lastIndex = 0; - - while (index >= 0) { - result.append(text, lastIndex, index); - result.append("["); - result.append(text, index, index + term.length()); - result.append("]"); - - lastIndex = index + term.length(); - index = text.toLowerCase().indexOf(term.toLowerCase(), lastIndex); - } - - result.append(text.substring(lastIndex)); - return result.toString(); + + // Join all args as the search term (supports multi-word searches) + String searchTerm = String.join(" ", args).toLowerCase(); + + System.out.println("Searching history for: '" + searchTerm + "'"); + System.out.println(); + + // Filter history + List matches = + history.stream().filter(cmd -> cmd.toLowerCase().contains(searchTerm)).toList(); + + if (matches.isEmpty()) { + System.out.println("No matching commands found."); + System.out.println("Tip: Search is case-insensitive and matches partial text."); + } else { + displayHistory(matches, searchTerm); + System.out.println(); + System.out.println("Found " + matches.size() + " matching command(s)."); } - - @Override - public String description() { - return "Search through command history"; + } + + /** + * Display history entries with line numbers. Optionally highlights the search term if provided. + */ + private void displayHistory(List commands, String searchTerm) { + int maxDigits = String.valueOf(commands.size()).length(); + + for (int i = 0; i < commands.size(); i++) { + String lineNum = String.format("%" + maxDigits + "d", i + 1); + String command = commands.get(i); + + // Highlight search term if provided (simple uppercase for visibility) + if (searchTerm != null && !searchTerm.isEmpty()) { + command = highlightTerm(command, searchTerm); + } + + System.out.println(" " + lineNum + " " + command); } - - @Override - public String usage() { - return "searchhistory [search_term]\n" + - " Examples:\n" + - " searchhistory - Show all history\n" + - " searchhistory dir - Find all 'dir' commands\n" + - " searchhistory cd .. - Find all 'cd ..' commands"; + } + + /** + * Simple highlighting by surrounding the search term with markers. For terminal with color + * support, you could use ANSI codes instead. + */ + private String highlightTerm(String text, String term) { + // Case-insensitive highlight + int index = text.toLowerCase().indexOf(term.toLowerCase()); + if (index == -1) { + return text; } + + StringBuilder result = new StringBuilder(); + int lastIndex = 0; + + while (index >= 0) { + result.append(text, lastIndex, index); + result.append("["); + result.append(text, index, index + term.length()); + result.append("]"); + + lastIndex = index + term.length(); + index = text.toLowerCase().indexOf(term.toLowerCase(), lastIndex); + } + + result.append(text.substring(lastIndex)); + return result.toString(); + } + + @Override + public String description() { + return "Search through command history"; + } + + @Override + public String usage() { + return "searchhistory [search_term]\n" + + " Examples:\n" + + " searchhistory - Show all history\n" + + " searchhistory dir - Find all 'dir' commands\n" + + " searchhistory cd .. - Find all 'cd ..' commands"; + } } diff --git a/src/main/java/com/mycmd/commands/SetCommand.java b/src/main/java/com/mycmd/commands/SetCommand.java index a011d3c..38135be 100644 --- a/src/main/java/com/mycmd/commands/SetCommand.java +++ b/src/main/java/com/mycmd/commands/SetCommand.java @@ -6,40 +6,40 @@ public class SetCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - // Print all environment variables - for (Map.Entry entry : context.getEnvVars().entrySet()) { - System.out.println(entry.getKey() + "=" + entry.getValue()); - } - return; - } - - String arg = args[0]; - if (arg.contains("=")) { - String[] parts = arg.split("=", 2); - String key = parts[0].trim(); - String value = parts[1].trim(); - context.setEnvVar(key, value); - System.out.println("Variable set: " + key + "=" + value); - } else { - String value = context.getEnvVar(arg); - if (value != null) { - System.out.println(arg + "=" + value); - } else { - System.out.println("Variable not found: " + arg); - } - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + // Print all environment variables + for (Map.Entry entry : context.getEnvVars().entrySet()) { + System.out.println(entry.getKey() + "=" + entry.getValue()); + } + return; } - @Override - public String description() { - return "Displays, sets, or retrieves shell environment variables."; + String arg = args[0]; + if (arg.contains("=")) { + String[] parts = arg.split("=", 2); + String key = parts[0].trim(); + String value = parts[1].trim(); + context.setEnvVar(key, value); + System.out.println("Variable set: " + key + "=" + value); + } else { + String value = context.getEnvVar(arg); + if (value != null) { + System.out.println(arg + "=" + value); + } else { + System.out.println("Variable not found: " + arg); + } } + } - @Override - public String usage() { - return "Usage: set [variable[=value]]"; - } + @Override + public String description() { + return "Displays, sets, or retrieves shell environment variables."; + } + + @Override + public String usage() { + return "Usage: set [variable[=value]]"; + } } diff --git a/src/main/java/com/mycmd/commands/SfcCommand.java b/src/main/java/com/mycmd/commands/SfcCommand.java index 50fc12b..96ebf56 100644 --- a/src/main/java/com/mycmd/commands/SfcCommand.java +++ b/src/main/java/com/mycmd/commands/SfcCommand.java @@ -14,63 +14,62 @@ */ public class SfcCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - String os = System.getProperty("os.name").toLowerCase(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("SFC (System File Checker) is only available on Windows systems."); - return; - } + if (!os.contains("win")) { + System.out.println("SFC (System File Checker) is only available on Windows systems."); + return; + } - if (args.length == 0) { - System.out.println("Microsoft Windows System File Checker"); - System.out.println("\nUsage:"); - System.out.println(" sfc [/scannow] [/verifyonly] [/scanfile=]"); - System.out.println("\nOptions:"); - System.out.println(" /scannow - Scans integrity of all protected system files"); - System.out.println(" /verifyonly - Scans integrity but does not repair"); - System.out.println(" /scanfile - Scans integrity of specific file"); - System.out.println("\nNote: Administrator privileges required."); - return; - } + if (args.length == 0) { + System.out.println("Microsoft Windows System File Checker"); + System.out.println("\nUsage:"); + System.out.println(" sfc [/scannow] [/verifyonly] [/scanfile=]"); + System.out.println("\nOptions:"); + System.out.println(" /scannow - Scans integrity of all protected system files"); + System.out.println(" /verifyonly - Scans integrity but does not repair"); + System.out.println(" /scanfile - Scans integrity of specific file"); + System.out.println("\nNote: Administrator privileges required."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder("sfc"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + StringBuilder cmdBuilder = new StringBuilder("sfc"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing sfc: " + e.getMessage()); - System.out.println("Administrator privileges may be required."); - } + } catch (Exception e) { + System.out.println("Error executing sfc: " + e.getMessage()); + System.out.println("Administrator privileges may be required."); } + } - @Override - public String description() { - return "System File Checker - Scans and verifies system files."; - } + @Override + public String description() { + return "System File Checker - Scans and verifies system files."; + } - @Override - public String usage() { - return "sfc [/scannow] [/verifyonly] [/scanfile=]"; - } + @Override + public String usage() { + return "sfc [/scannow] [/verifyonly] [/scanfile=]"; + } } diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index 046bb62..815d920 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -13,87 +13,82 @@ */ public class ShutdownCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Usage: shutdown [/i | /l | /s | /r | /a | /p | /h | /e]"); - System.out.println( - " [/f] [/m \\\\computer][/t xxx][/d [p:]xx:yy [/c \"comment\"]]"); - System.out.println("\n No args Display help."); - System.out.println( - " /i Display the GUI interface (must be the first option)."); - System.out.println(" /l Log off (cannot be used with /m or /d options)."); - System.out.println(" /s Shutdown the computer."); - System.out.println(" /r Shutdown and restart the computer."); - System.out.println(" /a Abort a system shutdown."); - System.out.println( - " /p Turn off the local computer with no time-out or warning."); - System.out.println(" /h Hibernate the local computer."); - System.out.println( - " /f Force running applications to close without warning."); - System.out.println( - " /t xxx Set time-out period before shutdown to xxx seconds."); - System.out.println("\nNote: Administrator privileges required."); - System.out.println("Warning: This command will actually shutdown/restart your system!"); - return; - } - - System.out.println("WARNING: This will execute a real shutdown command!"); - System.out.print("Are you sure you want to continue? (yes/no): "); - - java.util.Scanner scanner = new java.util.Scanner(System.in); - String confirmation = scanner.nextLine().trim().toLowerCase(); - - if (!confirmation.equals("yes")) { - System.out.println("Shutdown cancelled."); - return; - } - - try { - StringBuilder cmdBuilder = new StringBuilder("shutdown"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } - - ProcessBuilder pb = new ProcessBuilder(); - String os = System.getProperty("os.name").toLowerCase(); - - if (os.contains("win")) { - pb.command("cmd.exe", "/c", cmdBuilder.toString()); - } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) { - pb.command("sh", "-c", cmdBuilder.toString()); - } - - Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); - - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } - - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } - - process.waitFor(); - - } catch (Exception e) { - System.out.println("Error executing shutdown: " + e.getMessage()); - System.out.println("Administrator privileges may be required."); - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Usage: shutdown [/i | /l | /s | /r | /a | /p | /h | /e]"); + System.out.println( + " [/f] [/m \\\\computer][/t xxx][/d [p:]xx:yy [/c \"comment\"]]"); + System.out.println("\n No args Display help."); + System.out.println(" /i Display the GUI interface (must be the first option)."); + System.out.println(" /l Log off (cannot be used with /m or /d options)."); + System.out.println(" /s Shutdown the computer."); + System.out.println(" /r Shutdown and restart the computer."); + System.out.println(" /a Abort a system shutdown."); + System.out.println(" /p Turn off the local computer with no time-out or warning."); + System.out.println(" /h Hibernate the local computer."); + System.out.println(" /f Force running applications to close without warning."); + System.out.println(" /t xxx Set time-out period before shutdown to xxx seconds."); + System.out.println("\nNote: Administrator privileges required."); + System.out.println("Warning: This command will actually shutdown/restart your system!"); + return; } - @Override - public String description() { - return "Shuts down or restarts the computer."; + System.out.println("WARNING: This will execute a real shutdown command!"); + System.out.print("Are you sure you want to continue? (yes/no): "); + + java.util.Scanner scanner = new java.util.Scanner(System.in); + String confirmation = scanner.nextLine().trim().toLowerCase(); + + if (!confirmation.equals("yes")) { + System.out.println("Shutdown cancelled."); + return; } - @Override - public String usage() { - return "shutdown [/s | /r | /l] [/f] [/t seconds]"; + try { + StringBuilder cmdBuilder = new StringBuilder("shutdown"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } + + ProcessBuilder pb = new ProcessBuilder(); + String os = System.getProperty("os.name").toLowerCase(); + + if (os.contains("win")) { + pb.command("cmd.exe", "/c", cmdBuilder.toString()); + } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) { + pb.command("sh", "-c", cmdBuilder.toString()); + } + + Process process = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); + + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } + + process.waitFor(); + + } catch (Exception e) { + System.out.println("Error executing shutdown: " + e.getMessage()); + System.out.println("Administrator privileges may be required."); } + } + + @Override + public String description() { + return "Shuts down or restarts the computer."; + } + + @Override + public String usage() { + return "shutdown [/s | /r | /l] [/f] [/t seconds]"; + } } diff --git a/src/main/java/com/mycmd/commands/SortCommand.java b/src/main/java/com/mycmd/commands/SortCommand.java index aa1da68..b18a1aa 100644 --- a/src/main/java/com/mycmd/commands/SortCommand.java +++ b/src/main/java/com/mycmd/commands/SortCommand.java @@ -16,74 +16,73 @@ */ public class SortCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Sorts input and writes results to output."); - System.out.println("\nSORT [/R] [/+n] [/M kilobytes] [/L locale] [/REC recordbytes]"); - System.out.println(" [[drive1:][path1]filename1] [/T [drive2:][path2]]"); - System.out.println(" [/O [drive3:][path3]filename3]"); - System.out.println("\n /R Reverses the sort order"); - System.out.println( - " /+n Specifies the character number to begin each comparison"); - System.out.println(" filename1 Specifies the file to be sorted"); - return; - } - - boolean reverse = false; - int argIndex = 0; - - // Parse flags - while (argIndex < args.length && args[argIndex].startsWith("/")) { - String flag = args[argIndex].toUpperCase(); - if (flag.equals("/R")) reverse = true; - argIndex++; - } - - if (argIndex >= args.length) { - System.out.println("Missing filename."); - return; - } - - String filename = args[argIndex]; - java.io.File file = new java.io.File(filename); - - if (!file.isAbsolute()) { - file = new java.io.File(context.getCurrentDir(), filename); - } - - if (!file.exists()) { - System.out.println("File not found - " + filename); - return; - } - - List lines = new ArrayList<>(); - - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - while ((line = reader.readLine()) != null) { - lines.add(line); - } - } - - Collections.sort(lines); - - if (reverse) { - Collections.reverse(lines); - } - - for (String line : lines) { - System.out.println(line); - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Sorts input and writes results to output."); + System.out.println("\nSORT [/R] [/+n] [/M kilobytes] [/L locale] [/REC recordbytes]"); + System.out.println(" [[drive1:][path1]filename1] [/T [drive2:][path2]]"); + System.out.println(" [/O [drive3:][path3]filename3]"); + System.out.println("\n /R Reverses the sort order"); + System.out.println(" /+n Specifies the character number to begin each comparison"); + System.out.println(" filename1 Specifies the file to be sorted"); + return; } - @Override - public String description() { - return "Sorts the contents of a text file."; + boolean reverse = false; + int argIndex = 0; + + // Parse flags + while (argIndex < args.length && args[argIndex].startsWith("/")) { + String flag = args[argIndex].toUpperCase(); + if (flag.equals("/R")) reverse = true; + argIndex++; + } + + if (argIndex >= args.length) { + System.out.println("Missing filename."); + return; + } + + String filename = args[argIndex]; + java.io.File file = new java.io.File(filename); + + if (!file.isAbsolute()) { + file = new java.io.File(context.getCurrentDir(), filename); + } + + if (!file.exists()) { + System.out.println("File not found - " + filename); + return; } - @Override - public String usage() { - return "sort [/R] filename"; + List lines = new ArrayList<>(); + + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = reader.readLine()) != null) { + lines.add(line); + } + } + + Collections.sort(lines); + + if (reverse) { + Collections.reverse(lines); } + + for (String line : lines) { + System.out.println(line); + } + } + + @Override + public String description() { + return "Sorts the contents of a text file."; + } + + @Override + public String usage() { + return "sort [/R] filename"; + } } diff --git a/src/main/java/com/mycmd/commands/StartCommand.java b/src/main/java/com/mycmd/commands/StartCommand.java index 38167ee..e5bc33a 100644 --- a/src/main/java/com/mycmd/commands/StartCommand.java +++ b/src/main/java/com/mycmd/commands/StartCommand.java @@ -11,62 +11,62 @@ */ public class StartCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Starts a separate window to run a specified program or command."); - System.out.println("\nSTART [\"title\"] [/D path] [/I] [/MIN] [/MAX] [/WAIT]"); - System.out.println(" [/B] [command/program] [parameters]"); - System.out.println("\n \"title\" Title to display in window title bar."); - System.out.println(" /D path Specifies startup directory."); - System.out.println(" /MIN Start window minimized."); - System.out.println(" /MAX Start window maximized."); - System.out.println(" /WAIT Start application and wait for it to terminate."); - System.out.println(" /B Start application without creating a new window."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Starts a separate window to run a specified program or command."); + System.out.println("\nSTART [\"title\"] [/D path] [/I] [/MIN] [/MAX] [/WAIT]"); + System.out.println(" [/B] [command/program] [parameters]"); + System.out.println("\n \"title\" Title to display in window title bar."); + System.out.println(" /D path Specifies startup directory."); + System.out.println(" /MIN Start window minimized."); + System.out.println(" /MAX Start window maximized."); + System.out.println(" /WAIT Start application and wait for it to terminate."); + System.out.println(" /B Start application without creating a new window."); + return; + } - String os = System.getProperty("os.name").toLowerCase(); + String os = System.getProperty("os.name").toLowerCase(); - try { - if (os.contains("win")) { - // Windows - use start command - StringBuilder cmdBuilder = new StringBuilder("start"); - for (String arg : args) { - if (arg.contains(" ")) { - cmdBuilder.append(" \"").append(arg).append("\""); - } else { - cmdBuilder.append(" ").append(arg); - } - } + try { + if (os.contains("win")) { + // Windows - use start command + StringBuilder cmdBuilder = new StringBuilder("start"); + for (String arg : args) { + if (arg.contains(" ")) { + cmdBuilder.append(" \"").append(arg).append("\""); + } else { + cmdBuilder.append(" ").append(arg); + } + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - pb.directory(context.getCurrentDir()); - pb.start(); // Don't wait for completion + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + pb.directory(context.getCurrentDir()); + pb.start(); // Don't wait for completion - System.out.println("Started: " + String.join(" ", args)); + System.out.println("Started: " + String.join(" ", args)); - } else { - // Unix-like systems - use nohup or direct execution - ProcessBuilder pb = new ProcessBuilder(args); - pb.directory(context.getCurrentDir()); - pb.start(); + } else { + // Unix-like systems - use nohup or direct execution + ProcessBuilder pb = new ProcessBuilder(args); + pb.directory(context.getCurrentDir()); + pb.start(); - System.out.println("Started: " + String.join(" ", args)); - } + System.out.println("Started: " + String.join(" ", args)); + } - } catch (Exception e) { - System.out.println("Error starting process: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error starting process: " + e.getMessage()); } + } - @Override - public String description() { - return "Starts a separate window to run a specified program or command."; - } + @Override + public String description() { + return "Starts a separate window to run a specified program or command."; + } - @Override - public String usage() { - return "start [\"title\"] [/D path] [/MIN] [/MAX] [/WAIT] [command]"; - } + @Override + public String usage() { + return "start [\"title\"] [/D path] [/MIN] [/MAX] [/WAIT] [command]"; + } } diff --git a/src/main/java/com/mycmd/commands/SysteminfoCommand.java b/src/main/java/com/mycmd/commands/SysteminfoCommand.java index 7ceec88..e268456 100644 --- a/src/main/java/com/mycmd/commands/SysteminfoCommand.java +++ b/src/main/java/com/mycmd/commands/SysteminfoCommand.java @@ -12,63 +12,61 @@ import java.util.TimeZone; public class SysteminfoCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); - NumberFormat nf = NumberFormat.getInstance(); - Runtime rt = Runtime.getRuntime(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - sdf.setTimeZone(TimeZone.getDefault()); + @Override + public void execute(String[] args, ShellContext context) { + OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); + NumberFormat nf = NumberFormat.getInstance(); + Runtime rt = Runtime.getRuntime(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + sdf.setTimeZone(TimeZone.getDefault()); - String hostname; - try { - hostname = InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException e) { - hostname = System.getenv("COMPUTERNAME"); - if (hostname == null) hostname = System.getenv("HOSTNAME"); - if (hostname == null) hostname = "Unknown"; - } + String hostname; + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + hostname = System.getenv("COMPUTERNAME"); + if (hostname == null) hostname = System.getenv("HOSTNAME"); + if (hostname == null) hostname = "Unknown"; + } - long uptime = ManagementFactory.getRuntimeMXBean().getUptime(); - long bootTimeMillis = System.currentTimeMillis() - uptime; - long maxMem = rt.maxMemory(); - long totalMem = rt.totalMemory(); - long freeMem = rt.freeMemory(); - long usedMem = totalMem - freeMem; + long uptime = ManagementFactory.getRuntimeMXBean().getUptime(); + long bootTimeMillis = System.currentTimeMillis() - uptime; + long maxMem = rt.maxMemory(); + long totalMem = rt.totalMemory(); + long freeMem = rt.freeMemory(); + long usedMem = totalMem - freeMem; - System.out.println(); - System.out.println("Host Name: " + hostname); - System.out.println("OS Name: " + System.getProperty("os.name")); - System.out.println("OS Version: " + System.getProperty("os.version")); - System.out.println("Architecture: " + System.getProperty("os.arch")); - System.out.println("User Name: " + System.getProperty("user.name")); - System.out.println("Java Vendor: " + System.getProperty("java.vendor")); - System.out.println("Java VM: " + System.getProperty("java.vm.name")); - System.out.println("Available Processors: " + osBean.getAvailableProcessors()); - System.out.println("JVM Boot Time: " + sdf.format(new Date(bootTimeMillis))); - System.out.println("User Language: " + System.getProperty("user.language")); - System.out.println("User Country: " + System.getProperty("user.country")); - System.out.println("Home Directory: " + System.getProperty("user.home")); - System.out.println(); - System.out.println("JVM Memory (Heap):"); - System.out.println(" Total: " + nf.format(totalMem / (1024 * 1024)) + " MB"); - System.out.println(" Used: " + nf.format(usedMem / (1024 * 1024)) + " MB"); - System.out.println(" Free: " + nf.format(freeMem / (1024 * 1024)) + " MB"); - System.out.println( - " Max: " - + (maxMem == Long.MAX_VALUE - ? "No Limit" - : nf.format(maxMem / (1024 * 1024)) + " MB")); - System.out.println(); - } + System.out.println(); + System.out.println("Host Name: " + hostname); + System.out.println("OS Name: " + System.getProperty("os.name")); + System.out.println("OS Version: " + System.getProperty("os.version")); + System.out.println("Architecture: " + System.getProperty("os.arch")); + System.out.println("User Name: " + System.getProperty("user.name")); + System.out.println("Java Vendor: " + System.getProperty("java.vendor")); + System.out.println("Java VM: " + System.getProperty("java.vm.name")); + System.out.println("Available Processors: " + osBean.getAvailableProcessors()); + System.out.println("JVM Boot Time: " + sdf.format(new Date(bootTimeMillis))); + System.out.println("User Language: " + System.getProperty("user.language")); + System.out.println("User Country: " + System.getProperty("user.country")); + System.out.println("Home Directory: " + System.getProperty("user.home")); + System.out.println(); + System.out.println("JVM Memory (Heap):"); + System.out.println(" Total: " + nf.format(totalMem / (1024 * 1024)) + " MB"); + System.out.println(" Used: " + nf.format(usedMem / (1024 * 1024)) + " MB"); + System.out.println(" Free: " + nf.format(freeMem / (1024 * 1024)) + " MB"); + System.out.println( + " Max: " + + (maxMem == Long.MAX_VALUE ? "No Limit" : nf.format(maxMem / (1024 * 1024)) + " MB")); + System.out.println(); + } - @Override - public String description() { - return "Displays system and JVM information."; - } + @Override + public String description() { + return "Displays system and JVM information."; + } - @Override - public String usage() { - return "systeminfo"; - } + @Override + public String usage() { + return "systeminfo"; + } } diff --git a/src/main/java/com/mycmd/commands/TaskkillCommand.java b/src/main/java/com/mycmd/commands/TaskkillCommand.java index a1b59ac..2145891 100644 --- a/src/main/java/com/mycmd/commands/TaskkillCommand.java +++ b/src/main/java/com/mycmd/commands/TaskkillCommand.java @@ -14,65 +14,63 @@ */ public class TaskkillCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("TASKKILL [/S system [/U username [/P [password]]]]"); - System.out.println( - " { [/FI filter] [/PID processid | /IM imagename] } [/T] [/F]"); - System.out.println("\nDescription:"); - System.out.println( - " This tool is used to terminate tasks by process id (PID) or image name."); - System.out.println("\nExamples:"); - System.out.println(" taskkill /IM notepad.exe"); - System.out.println(" taskkill /PID 1234"); - System.out.println(" taskkill /F /IM chrome.exe"); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("TASKKILL [/S system [/U username [/P [password]]]]"); + System.out.println(" { [/FI filter] [/PID processid | /IM imagename] } [/T] [/F]"); + System.out.println("\nDescription:"); + System.out.println( + " This tool is used to terminate tasks by process id (PID) or image name."); + System.out.println("\nExamples:"); + System.out.println(" taskkill /IM notepad.exe"); + System.out.println(" taskkill /PID 1234"); + System.out.println(" taskkill /F /IM chrome.exe"); + return; + } - String os = System.getProperty("os.name").toLowerCase(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - try { - StringBuilder cmdBuilder = new StringBuilder("taskkill"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + if (os.contains("win")) { + try { + StringBuilder cmdBuilder = new StringBuilder("taskkill"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing taskkill: " + e.getMessage()); - } - } else { - // Unix-like systems - use kill command - System.out.println("On Unix-like systems, use 'kill' command instead."); - System.out.println("Example: kill -9 "); - } + } catch (Exception e) { + System.out.println("Error executing taskkill: " + e.getMessage()); + } + } else { + // Unix-like systems - use kill command + System.out.println("On Unix-like systems, use 'kill' command instead."); + System.out.println("Example: kill -9 "); } + } - @Override - public String description() { - return "Terminates one or more processes."; - } + @Override + public String description() { + return "Terminates one or more processes."; + } - @Override - public String usage() { - return "taskkill [/F] [/PID processid | /IM imagename]"; - } + @Override + public String usage() { + return "taskkill [/F] [/PID processid | /IM imagename]"; + } } diff --git a/src/main/java/com/mycmd/commands/TasklistCommand.java b/src/main/java/com/mycmd/commands/TasklistCommand.java index b911394..52a6109 100644 --- a/src/main/java/com/mycmd/commands/TasklistCommand.java +++ b/src/main/java/com/mycmd/commands/TasklistCommand.java @@ -14,66 +14,63 @@ */ public class TasklistCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - System.out.println(); - System.out.printf("%-40s %10s %15s%n", "Image Name", "PID", "Memory Usage"); - System.out.println("=".repeat(70)); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + System.out.println(); + System.out.printf("%-40s %10s %15s%n", "Image Name", "PID", "Memory Usage"); + System.out.println("=".repeat(70)); - // Get current Java process information - RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); - String jvmName = runtimeMXBean.getName(); - String[] parts = jvmName.split("@"); - String pid = parts.length > 0 ? parts[0] : "Unknown"; + // Get current Java process information + RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + String jvmName = runtimeMXBean.getName(); + String[] parts = jvmName.split("@"); + String pid = parts.length > 0 ? parts[0] : "Unknown"; - // Get memory info - Runtime runtime = Runtime.getRuntime(); - long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024); // MB + // Get memory info + Runtime runtime = Runtime.getRuntime(); + long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024); // MB - System.out.printf("%-40s %10s %12s MB%n", "java.exe", pid, usedMemory); + System.out.printf("%-40s %10s %12s MB%n", "java.exe", pid, usedMemory); - // Try to get system processes using ProcessHandle (Java 9+) - try { - ProcessHandle.allProcesses() - .limit(20) // Limit to first 20 processes - .forEach( - process -> { - ProcessHandle.Info info = process.info(); - long processPid = process.pid(); - String command = info.command().orElse("Unknown"); + // Try to get system processes using ProcessHandle (Java 9+) + try { + ProcessHandle.allProcesses() + .limit(20) // Limit to first 20 processes + .forEach( + process -> { + ProcessHandle.Info info = process.info(); + long processPid = process.pid(); + String command = info.command().orElse("Unknown"); - // Extract just the executable name from full path - String execName = command; - if (command.contains("/") || command.contains("\\")) { - int lastSlash = - Math.max( - command.lastIndexOf('/'), - command.lastIndexOf('\\')); - execName = command.substring(lastSlash + 1); - } + // Extract just the executable name from full path + String execName = command; + if (command.contains("/") || command.contains("\\")) { + int lastSlash = Math.max(command.lastIndexOf('/'), command.lastIndexOf('\\')); + execName = command.substring(lastSlash + 1); + } - // Truncate long names - if (execName.length() > 40) { - execName = execName.substring(0, 37) + "..."; - } + // Truncate long names + if (execName.length() > 40) { + execName = execName.substring(0, 37) + "..."; + } - System.out.printf("%-40s %10d %15s%n", execName, processPid, "N/A"); - }); - } catch (Exception e) { - // ProcessHandle not available or error accessing processes - System.out.println("\n[Additional process information not available]"); - } - - System.out.println(); + System.out.printf("%-40s %10d %15s%n", execName, processPid, "N/A"); + }); + } catch (Exception e) { + // ProcessHandle not available or error accessing processes + System.out.println("\n[Additional process information not available]"); } - @Override - public String description() { - return "Display a list of currently running processes."; - } + System.out.println(); + } - @Override - public String usage() { - return "tasklist"; - } + @Override + public String description() { + return "Display a list of currently running processes."; + } + + @Override + public String usage() { + return "tasklist"; + } } diff --git a/src/main/java/com/mycmd/commands/TelnetCommand.java b/src/main/java/com/mycmd/commands/TelnetCommand.java index c8dc9f5..72ad891 100644 --- a/src/main/java/com/mycmd/commands/TelnetCommand.java +++ b/src/main/java/com/mycmd/commands/TelnetCommand.java @@ -13,85 +13,85 @@ */ public class TelnetCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 1) { - System.out.println("Usage: " + usage()); - return; - } - - String host = args[0]; - int port = 23; - if (args.length >= 2) { - try { - port = Integer.parseInt(args[1]); - } catch (NumberFormatException e) { - System.out.println("Invalid port: " + args[1]); - return; - } - } - - try (Socket socket = new Socket(host, port)) { - socket.setSoTimeout(0); // blocking reads - System.out.println("Connected to " + host + ":" + port + " (type 'exit' to quit)"); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 1) { + System.out.println("Usage: " + usage()); + return; + } - // Reader thread: prints remote data to stdout - Thread reader = - new Thread( - () -> { - try (InputStream in = socket.getInputStream(); - InputStreamReader isr = new InputStreamReader(in); - BufferedReader br = new BufferedReader(isr)) { + String host = args[0]; + int port = 23; + if (args.length >= 2) { + try { + port = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + System.out.println("Invalid port: " + args[1]); + return; + } + } - char[] buffer = new char[2048]; - int read; - while ((read = br.read(buffer)) != -1) { - System.out.print(new String(buffer, 0, read)); - System.out.flush(); - } - } catch (IOException ignored) { - // socket closed or stream ended - } - }, - "telnet-reader"); - reader.setDaemon(true); - reader.start(); + try (Socket socket = new Socket(host, port)) { + socket.setSoTimeout(0); // blocking reads + System.out.println("Connected to " + host + ":" + port + " (type 'exit' to quit)"); - // Writer loop: read stdin and send to remote - try (OutputStream out = socket.getOutputStream(); - OutputStreamWriter osw = new OutputStreamWriter(out); - BufferedWriter bw = new BufferedWriter(osw); - BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in))) { + // Reader thread: prints remote data to stdout + Thread reader = + new Thread( + () -> { + try (InputStream in = socket.getInputStream(); + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr)) { - String line; - while ((line = stdin.readLine()) != null) { - if ("exit".equalsIgnoreCase(line.trim())) break; - bw.write(line); - bw.write("\r\n"); // typical telnet line ending - bw.flush(); + char[] buffer = new char[2048]; + int read; + while ((read = br.read(buffer)) != -1) { + System.out.print(new String(buffer, 0, read)); + System.out.flush(); + } + } catch (IOException ignored) { + // socket closed or stream ended } - } catch (IOException ignored) { - // stdin/socket error, will disconnect - } + }, + "telnet-reader"); + reader.setDaemon(true); + reader.start(); + + // Writer loop: read stdin and send to remote + try (OutputStream out = socket.getOutputStream(); + OutputStreamWriter osw = new OutputStreamWriter(out); + BufferedWriter bw = new BufferedWriter(osw); + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in))) { - // ensure socket closes to stop reader - try { - socket.close(); - } catch (IOException ignored) { - } - System.out.println("\nDisconnected."); - } catch (IOException e) { - System.out.println("Connection failed: " + e.getMessage()); + String line; + while ((line = stdin.readLine()) != null) { + if ("exit".equalsIgnoreCase(line.trim())) break; + bw.write(line); + bw.write("\r\n"); // typical telnet line ending + bw.flush(); } - } + } catch (IOException ignored) { + // stdin/socket error, will disconnect + } - @Override - public String description() { - return "Simple TCP client for interactive sessions."; + // ensure socket closes to stop reader + try { + socket.close(); + } catch (IOException ignored) { + } + System.out.println("\nDisconnected."); + } catch (IOException e) { + System.out.println("Connection failed: " + e.getMessage()); } + } - @Override - public String usage() { - return "telnet [port]"; - } + @Override + public String description() { + return "Simple TCP client for interactive sessions."; + } + + @Override + public String usage() { + return "telnet [port]"; + } } diff --git a/src/main/java/com/mycmd/commands/TimeCommand.java b/src/main/java/com/mycmd/commands/TimeCommand.java index 957fd78..e2bc2cd 100644 --- a/src/main/java/com/mycmd/commands/TimeCommand.java +++ b/src/main/java/com/mycmd/commands/TimeCommand.java @@ -20,27 +20,27 @@ * Example output: "The current time is: 13.5.07.12" */ public class TimeCommand implements Command { - /** - * Print the current time. - * - * @param args ignored for this command; may be empty or contain unused tokens. - * @param context the current shell context; not used by this command. - */ - @Override - public void execute(String[] args, ShellContext context) { - LocalTime now = LocalTime.now(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H.mm.ss.SS"); - String formattedTime = now.format(formatter); - System.out.println("The current time is: " + formattedTime); - } + /** + * Print the current time. + * + * @param args ignored for this command; may be empty or contain unused tokens. + * @param context the current shell context; not used by this command. + */ + @Override + public void execute(String[] args, ShellContext context) { + LocalTime now = LocalTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H.mm.ss.SS"); + String formattedTime = now.format(formatter); + System.out.println("The current time is: " + formattedTime); + } - @Override - public String description() { - return "Display the current local time."; - } + @Override + public String description() { + return "Display the current local time."; + } - @Override - public String usage() { - return "time"; - } + @Override + public String usage() { + return "time"; + } } diff --git a/src/main/java/com/mycmd/commands/TimeoutCommand.java b/src/main/java/com/mycmd/commands/TimeoutCommand.java index fd429f8..4d736aa 100644 --- a/src/main/java/com/mycmd/commands/TimeoutCommand.java +++ b/src/main/java/com/mycmd/commands/TimeoutCommand.java @@ -6,183 +6,183 @@ import java.util.concurrent.atomic.AtomicBoolean; public class TimeoutCommand implements Command { - /** - * Execute the timeout command. - * - *

This command will wait for the specified number of seconds before continuing. If the user - * presses Enter before the timeout expires, the command will terminate immediately. - * - * @param args The arguments to the command. - * @param context The context of the shell. - * @throws IOException If an I/O error occurs. - */ - @Override - public void execute(String[] args, ShellContext context) { - int seconds = -1; - boolean hasSecondsArg = false; - boolean hasSlashT = false; - boolean noBreak = false; + /** + * Execute the timeout command. + * + *

This command will wait for the specified number of seconds before continuing. If the user + * presses Enter before the timeout expires, the command will terminate immediately. + * + * @param args The arguments to the command. + * @param context The context of the shell. + * @throws IOException If an I/O error occurs. + */ + @Override + public void execute(String[] args, ShellContext context) { + int seconds = -1; + boolean hasSecondsArg = false; + boolean hasSlashT = false; + boolean noBreak = false; - for (int i = 0; i < args.length; i++) { - if (args[i].equalsIgnoreCase("/t") - && i + 1 < args.length - && args[i + 1].matches("[+-]?\\d+")) { - if (hasSlashT) { - System.out.println( - "Error: Invalid syntax. '/t' option is not allowed more than '1' time(s)."); - return; - } - seconds = Integer.parseInt(args[i + 1]); - i++; - hasSecondsArg = true; - hasSlashT = true; - } else if (args[i].equalsIgnoreCase("/nobreak")) { - if (noBreak) { - System.out.println( - "Error: Invalid syntax. '/nobreak' option is not allowed more than '1' time(s)."); - return; - } - noBreak = true; - } else if (args[i].matches("[+-]?\\d+")) { - if (hasSecondsArg) { - System.out.println( - "Error: Invalid syntax. Default option is not allowed more than '1' time(s)."); - return; - } - seconds = Integer.parseInt(args[i]); - hasSecondsArg = true; - } else if (args[i].equalsIgnoreCase("/t")) { - System.out.println("Error: Invalid syntax. Value expected for '/t'."); - return; - } else { - System.out.println("Error: Invalid syntax. Unrecognized argument: " + args[i]); - return; - } + for (int i = 0; i < args.length; i++) { + if (args[i].equalsIgnoreCase("/t") + && i + 1 < args.length + && args[i + 1].matches("[+-]?\\d+")) { + if (hasSlashT) { + System.out.println( + "Error: Invalid syntax. '/t' option is not allowed more than '1' time(s)."); + return; } - - if (!hasSecondsArg) { - System.out.println("Error: Invalid syntax. Seconds value is required."); - return; + seconds = Integer.parseInt(args[i + 1]); + i++; + hasSecondsArg = true; + hasSlashT = true; + } else if (args[i].equalsIgnoreCase("/nobreak")) { + if (noBreak) { + System.out.println( + "Error: Invalid syntax. '/nobreak' option is not allowed more than '1' time(s)."); + return; } - - if (seconds < -1 || seconds > 99999) { - System.out.println( - "Error: Invalid value for timeout specified. Valid range is 0-99999 seconds."); - return; + noBreak = true; + } else if (args[i].matches("[+-]?\\d+")) { + if (hasSecondsArg) { + System.out.println( + "Error: Invalid syntax. Default option is not allowed more than '1' time(s)."); + return; } + seconds = Integer.parseInt(args[i]); + hasSecondsArg = true; + } else if (args[i].equalsIgnoreCase("/t")) { + System.out.println("Error: Invalid syntax. Value expected for '/t'."); + return; + } else { + System.out.println("Error: Invalid syntax. Unrecognized argument: " + args[i]); + return; + } + } - if (seconds == -1) { - System.out.println(); - PauseCommand pauseCmd = new PauseCommand(); - pauseCmd.execute(new String[0], context); - return; - } + if (!hasSecondsArg) { + System.out.println("Error: Invalid syntax. Seconds value is required."); + return; + } - AtomicBoolean interrupted = new AtomicBoolean(false); - AtomicBoolean stopInput = new AtomicBoolean(false); - Thread inputThread = null; + if (seconds < -1 || seconds > 99999) { + System.out.println( + "Error: Invalid value for timeout specified. Valid range is 0-99999 seconds."); + return; + } - if (!noBreak) { - inputThread = - new Thread( - () -> { - try { - // Poll non-blocking so we can stop the thread - // deterministically. - while (!stopInput.get()) { - if (System.in.available() > 0) { - int r = System.in.read(); - // Treat CR or LF as Enter across platforms - if (r == '\n' || r == '\r') { - interrupted.set(true); - break; - } - } else { - try { - Thread.sleep(25); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - break; - } - } - } - } catch (IOException e) { - // Best-effort only; fall through. - } - }); - inputThread.setDaemon(true); - inputThread.start(); - } - System.out.println(); + if (seconds == -1) { + System.out.println(); + PauseCommand pauseCmd = new PauseCommand(); + pauseCmd.execute(new String[0], context); + return; + } - for (; seconds > 0; seconds--) { - if (!noBreak && interrupted.get()) { - System.out.println("\r"); - System.out.println(); - if (inputThread != null) { - stopInput.set(true); - try { - inputThread.join(200); - } catch (InterruptedException ie) { + AtomicBoolean interrupted = new AtomicBoolean(false); + AtomicBoolean stopInput = new AtomicBoolean(false); + Thread inputThread = null; + + if (!noBreak) { + inputThread = + new Thread( + () -> { + try { + // Poll non-blocking so we can stop the thread + // deterministically. + while (!stopInput.get()) { + if (System.in.available() > 0) { + int r = System.in.read(); + // Treat CR or LF as Enter across platforms + if (r == '\n' || r == '\r') { + interrupted.set(true); + break; + } + } else { + try { + Thread.sleep(25); + } catch (InterruptedException ie) { Thread.currentThread().interrupt(); + break; + } } + } + } catch (IOException e) { + // Best-effort only; fall through. } - return; - } + }); + inputThread.setDaemon(true); + inputThread.start(); + } + System.out.println(); - System.out.print( - "\rWaiting for " - + seconds - + " seconds, press " - + (noBreak ? "CTRL+C to quit ..." : "enter key to continue ...")); - System.out.flush(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - if (noBreak) { - continue; - } - System.out.println(); - Thread.currentThread().interrupt(); - break; - } + for (; seconds > 0; seconds--) { + if (!noBreak && interrupted.get()) { + System.out.println("\r"); + System.out.println(); + if (inputThread != null) { + stopInput.set(true); + try { + inputThread.join(200); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } } + return; + } - // Normal completion: stop the input thread before draining. - if (!noBreak && inputThread != null) { - stopInput.set(true); - try { - inputThread.join(200); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } - } - try { - // Drain any remaining bytes so subsequent commands don't immediately see - // leftover input. This is a best-effort drain; System.in.available() may - // not be supported on all streams, but for typical console streams it helps. - while (System.in.available() > 0) { - System.in.read(); - } - } catch (IOException e) { - // Ignore: if we can't drain the stream it's non-fatal; any leftover input - // will be handled by the next read and is acceptable. + System.out.print( + "\rWaiting for " + + seconds + + " seconds, press " + + (noBreak ? "CTRL+C to quit ..." : "enter key to continue ...")); + System.out.flush(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + if (noBreak) { + continue; } - - System.out.println("\r"); System.out.println(); + Thread.currentThread().interrupt(); + break; + } } - @Override - public String description() { - return "Sets a timeout for command execution."; + // Normal completion: stop the input thread before draining. + if (!noBreak && inputThread != null) { + stopInput.set(true); + try { + inputThread.join(200); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } } - - @Override - public String usage() { - return "timeout \n" - + "timeout /t \n" - + "timeout /t /nobreak\n" - + "timeout /t -1"; + try { + // Drain any remaining bytes so subsequent commands don't immediately see + // leftover input. This is a best-effort drain; System.in.available() may + // not be supported on all streams, but for typical console streams it helps. + while (System.in.available() > 0) { + System.in.read(); + } + } catch (IOException e) { + // Ignore: if we can't drain the stream it's non-fatal; any leftover input + // will be handled by the next read and is acceptable. } + + System.out.println("\r"); + System.out.println(); + } + + @Override + public String description() { + return "Sets a timeout for command execution."; + } + + @Override + public String usage() { + return "timeout \n" + + "timeout /t \n" + + "timeout /t /nobreak\n" + + "timeout /t -1"; + } } diff --git a/src/main/java/com/mycmd/commands/TitleCommand.java b/src/main/java/com/mycmd/commands/TitleCommand.java index 9453707..7eeadc3 100644 --- a/src/main/java/com/mycmd/commands/TitleCommand.java +++ b/src/main/java/com/mycmd/commands/TitleCommand.java @@ -17,23 +17,23 @@ * information is displayed. */ public class TitleCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length > 0) { - String title = String.join(" ", args); - System.out.println("\033]0;" + title + "\007"); - } else { - System.out.println("Usage: " + usage()); - } + @Override + public void execute(String[] args, ShellContext context) { + if (args.length > 0) { + String title = String.join(" ", args); + System.out.println("\033]0;" + title + "\007"); + } else { + System.out.println("Usage: " + usage()); } + } - @Override - public String description() { - return "Set the terminal window title."; - } + @Override + public String description() { + return "Set the terminal window title."; + } - @Override - public String usage() { - return "title "; - } + @Override + public String usage() { + return "title "; + } } diff --git a/src/main/java/com/mycmd/commands/TouchCommand.java b/src/main/java/com/mycmd/commands/TouchCommand.java index 33ea349..6047f96 100644 --- a/src/main/java/com/mycmd/commands/TouchCommand.java +++ b/src/main/java/com/mycmd/commands/TouchCommand.java @@ -18,30 +18,30 @@ * indicating whether a new file was created or an existing file's timestamp was updated. */ public class TouchCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 1) { // โœ… Check for at least 1 argument - System.out.println("Usage: " + usage()); - return; - } - - File file = new File(context.getCurrentDir(), args[0]); // โœ… Use args[0] - if (file.createNewFile()) { - System.out.println("File created: " + args[0]); // โœ… Use args[0] - } else { - // Update timestamp - file.setLastModified(System.currentTimeMillis()); - System.out.println("File timestamp updated: " + args[0]); // โœ… Use args[0] - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 1) { // โœ… Check for at least 1 argument + System.out.println("Usage: " + usage()); + return; } - @Override - public String description() { - return "Create a new empty file or update the timestamp of an existing file."; + File file = new File(context.getCurrentDir(), args[0]); // โœ… Use args[0] + if (file.createNewFile()) { + System.out.println("File created: " + args[0]); // โœ… Use args[0] + } else { + // Update timestamp + file.setLastModified(System.currentTimeMillis()); + System.out.println("File timestamp updated: " + args[0]); // โœ… Use args[0] } + } - @Override - public String usage() { - return "touch "; - } + @Override + public String description() { + return "Create a new empty file or update the timestamp of an existing file."; + } + + @Override + public String usage() { + return "touch "; + } } diff --git a/src/main/java/com/mycmd/commands/TracertCommand.java b/src/main/java/com/mycmd/commands/TracertCommand.java index c9fc341..afbf8d6 100644 --- a/src/main/java/com/mycmd/commands/TracertCommand.java +++ b/src/main/java/com/mycmd/commands/TracertCommand.java @@ -13,63 +13,62 @@ */ public class TracertCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Usage: tracert [-d] [-h maximum_hops] [-w timeout] target_name"); - System.out.println("\nTraces the route packets take to a network host."); - System.out.println("\nOptions:"); - System.out.println(" -d Do not resolve addresses to hostnames."); - System.out.println(" -h maximum_hops Maximum number of hops to search for target."); - System.out.println(" -w timeout Wait timeout milliseconds for each reply."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Usage: tracert [-d] [-h maximum_hops] [-w timeout] target_name"); + System.out.println("\nTraces the route packets take to a network host."); + System.out.println("\nOptions:"); + System.out.println(" -d Do not resolve addresses to hostnames."); + System.out.println(" -h maximum_hops Maximum number of hops to search for target."); + System.out.println(" -w timeout Wait timeout milliseconds for each reply."); + return; + } - try { - StringBuilder cmdBuilder = new StringBuilder(); - String os = System.getProperty("os.name").toLowerCase(); + try { + StringBuilder cmdBuilder = new StringBuilder(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - cmdBuilder.append("tracert"); - } else { - cmdBuilder.append("traceroute"); - } + if (os.contains("win")) { + cmdBuilder.append("tracert"); + } else { + cmdBuilder.append("traceroute"); + } - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - ProcessBuilder pb = new ProcessBuilder(); + ProcessBuilder pb = new ProcessBuilder(); - if (os.contains("win")) { - pb.command("cmd.exe", "/c", cmdBuilder.toString()); - } else { - pb.command("sh", "-c", cmdBuilder.toString()); - } + if (os.contains("win")) { + pb.command("cmd.exe", "/c", cmdBuilder.toString()); + } else { + pb.command("sh", "-c", cmdBuilder.toString()); + } - Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); + Process process = pb.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing tracert: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing tracert: " + e.getMessage()); } + } - @Override - public String description() { - return "Traces the route packets take to a network host."; - } + @Override + public String description() { + return "Traces the route packets take to a network host."; + } - @Override - public String usage() { - return "tracert [-d] [-h maximum_hops] target_name"; - } + @Override + public String usage() { + return "tracert [-d] [-h maximum_hops] target_name"; + } } diff --git a/src/main/java/com/mycmd/commands/TreeCommand.java b/src/main/java/com/mycmd/commands/TreeCommand.java index 863ba0b..f68df8b 100644 --- a/src/main/java/com/mycmd/commands/TreeCommand.java +++ b/src/main/java/com/mycmd/commands/TreeCommand.java @@ -20,43 +20,43 @@ * beneath the current location. */ public class TreeCommand implements Command { - public void execute(String[] args, ShellContext context) { - File[] files = context.getCurrentDir().listFiles(); + public void execute(String[] args, ShellContext context) { + File[] files = context.getCurrentDir().listFiles(); - if (files == null || files.length == 0) { - System.out.println("No files found."); - return; - } - - System.out.println(context.getCurrentDir().getAbsolutePath()); - printDirectory(files, "", true); - System.out.println(); + if (files == null || files.length == 0) { + System.out.println("No files found."); + return; } - private void printDirectory(File[] files, String prefix, boolean isLast) { - if (files == null || files.length == 0) return; + System.out.println(context.getCurrentDir().getAbsolutePath()); + printDirectory(files, "", true); + System.out.println(); + } - for (int i = 0; i < files.length; i++) { - File f = files[i]; - if (f.isHidden()) continue; + private void printDirectory(File[] files, String prefix, boolean isLast) { + if (files == null || files.length == 0) return; - boolean last = (i == files.length - 1); - System.out.println(prefix + (last ? "โ””โ”€โ”€โ”€" : "โ”œโ”€โ”€โ”€") + f.getName()); + for (int i = 0; i < files.length; i++) { + File f = files[i]; + if (f.isHidden()) continue; - if (f.isDirectory()) { - String newPrefix = prefix + (last ? " " : "โ”‚ "); - printDirectory(f.listFiles(), newPrefix, last); - } - } - } + boolean last = (i == files.length - 1); + System.out.println(prefix + (last ? "โ””โ”€โ”€โ”€" : "โ”œโ”€โ”€โ”€") + f.getName()); - @Override - public String description() { - return "Display the directory tree structure."; + if (f.isDirectory()) { + String newPrefix = prefix + (last ? " " : "โ”‚ "); + printDirectory(f.listFiles(), newPrefix, last); + } } + } - @Override - public String usage() { - return "tree"; - } + @Override + public String description() { + return "Display the directory tree structure."; + } + + @Override + public String usage() { + return "tree"; + } } diff --git a/src/main/java/com/mycmd/commands/TypeCommand.java b/src/main/java/com/mycmd/commands/TypeCommand.java index fdf8742..bbf3864 100644 --- a/src/main/java/com/mycmd/commands/TypeCommand.java +++ b/src/main/java/com/mycmd/commands/TypeCommand.java @@ -20,34 +20,34 @@ *

Note: Best suited for text files. Binary files may produce garbled output. */ public class TypeCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - if (args.length == 0) { - System.out.println("Usage: " + usage()); - return; - } - File file = new File(context.getCurrentDir(), args[0]); - if (!file.exists() || !file.isFile()) { - System.out.println("File not found."); - return; - } - try (BufferedReader br = new BufferedReader(new FileReader(file))) { - String line; - while ((line = br.readLine()) != null) { - System.out.println(line); - } - } catch (IOException e) { - System.out.println("Error reading file: " + e.getMessage()); - } + @Override + public void execute(String[] args, ShellContext context) { + if (args.length == 0) { + System.out.println("Usage: " + usage()); + return; } - - @Override - public String description() { - return "Display the contents of a text file."; + File file = new File(context.getCurrentDir(), args[0]); + if (!file.exists() || !file.isFile()) { + System.out.println("File not found."); + return; } - - @Override - public String usage() { - return "type "; + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line; + while ((line = br.readLine()) != null) { + System.out.println(line); + } + } catch (IOException e) { + System.out.println("Error reading file: " + e.getMessage()); } + } + + @Override + public String description() { + return "Display the contents of a text file."; + } + + @Override + public String usage() { + return "type "; + } } diff --git a/src/main/java/com/mycmd/commands/UnaliasCommand.java b/src/main/java/com/mycmd/commands/UnaliasCommand.java index 1a4dabe..996db2f 100644 --- a/src/main/java/com/mycmd/commands/UnaliasCommand.java +++ b/src/main/java/com/mycmd/commands/UnaliasCommand.java @@ -5,31 +5,31 @@ import java.io.IOException; public class UnaliasCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args == null || args.length == 0) { - System.out.println("Usage: " + usage()); - return; - } - - for (String name : args) { - if (name == null || name.trim().isEmpty()) continue; - if (context.hasAlias(name)) { - context.removeAlias(name); - System.out.println("Removed alias: " + name); - } else { - System.out.println("Alias not found: " + name); - } - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args == null || args.length == 0) { + System.out.println("Usage: " + usage()); + return; } - @Override - public String description() { - return "Remove one or more aliases."; + for (String name : args) { + if (name == null || name.trim().isEmpty()) continue; + if (context.hasAlias(name)) { + context.removeAlias(name); + System.out.println("Removed alias: " + name); + } else { + System.out.println("Alias not found: " + name); + } } + } - @Override - public String usage() { - return "unalias name [name2 ...]"; - } + @Override + public String description() { + return "Remove one or more aliases."; + } + + @Override + public String usage() { + return "unalias name [name2 ...]"; + } } diff --git a/src/main/java/com/mycmd/commands/UptimeCommand.java b/src/main/java/com/mycmd/commands/UptimeCommand.java index f96e389..6e05557 100644 --- a/src/main/java/com/mycmd/commands/UptimeCommand.java +++ b/src/main/java/com/mycmd/commands/UptimeCommand.java @@ -20,34 +20,34 @@ *

This is useful for monitoring how long a shell session has been active. */ public class UptimeCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - Instant startTime = context.getStartTime(); - Instant now = Instant.now(); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + Instant startTime = context.getStartTime(); + Instant now = Instant.now(); - // Calculate duration between start time and now - Duration uptime = Duration.between(startTime, now); + // Calculate duration between start time and now + Duration uptime = Duration.between(startTime, now); - long seconds = uptime.getSeconds(); - long days = seconds / 86400; - long hours = (seconds % 86400) / 3600; - long minutes = (seconds % 3600) / 60; - long secs = seconds % 60; + long seconds = uptime.getSeconds(); + long days = seconds / 86400; + long hours = (seconds % 86400) / 3600; + long minutes = (seconds % 3600) / 60; + long secs = seconds % 60; - System.out.print("Uptime: "); - if (days > 0) { - System.out.print(days + " day" + (days != 1 ? "s" : "") + ", "); - } - System.out.printf("%02d:%02d:%02d%n", hours, minutes, secs); + System.out.print("Uptime: "); + if (days > 0) { + System.out.print(days + " day" + (days != 1 ? "s" : "") + ", "); } + System.out.printf("%02d:%02d:%02d%n", hours, minutes, secs); + } - @Override - public String description() { - return "Display how long the shell has been running since startup."; - } + @Override + public String description() { + return "Display how long the shell has been running since startup."; + } - @Override - public String usage() { - return "uptime"; - } + @Override + public String usage() { + return "uptime"; + } } diff --git a/src/main/java/com/mycmd/commands/VerifyCommand.java b/src/main/java/com/mycmd/commands/VerifyCommand.java index e4501d2..633a771 100644 --- a/src/main/java/com/mycmd/commands/VerifyCommand.java +++ b/src/main/java/com/mycmd/commands/VerifyCommand.java @@ -12,35 +12,35 @@ */ public class VerifyCommand implements Command { - private static boolean verifyEnabled = false; - - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("VERIFY is " + (verifyEnabled ? "on" : "off") + "."); - return; - } - - String option = args[0].toUpperCase(); - - if (option.equals("ON")) { - verifyEnabled = true; - System.out.println("VERIFY is on."); - } else if (option.equals("OFF")) { - verifyEnabled = false; - System.out.println("VERIFY is off."); - } else { - System.out.println("Must specify ON or OFF."); - } - } + private static boolean verifyEnabled = false; - @Override - public String description() { - return "Enables or disables file verification."; + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("VERIFY is " + (verifyEnabled ? "on" : "off") + "."); + return; } - @Override - public String usage() { - return "verify [ON | OFF]"; + String option = args[0].toUpperCase(); + + if (option.equals("ON")) { + verifyEnabled = true; + System.out.println("VERIFY is on."); + } else if (option.equals("OFF")) { + verifyEnabled = false; + System.out.println("VERIFY is off."); + } else { + System.out.println("Must specify ON or OFF."); } + } + + @Override + public String description() { + return "Enables or disables file verification."; + } + + @Override + public String usage() { + return "verify [ON | OFF]"; + } } diff --git a/src/main/java/com/mycmd/commands/VersionCommand.java b/src/main/java/com/mycmd/commands/VersionCommand.java index 13e6287..975bc40 100644 --- a/src/main/java/com/mycmd/commands/VersionCommand.java +++ b/src/main/java/com/mycmd/commands/VersionCommand.java @@ -14,18 +14,18 @@ *

Note: This command does not accept any arguments and always displays the same version string. */ public class VersionCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - System.out.println("MyCMD Java Shell v1.0"); - } + @Override + public void execute(String[] args, ShellContext context) { + System.out.println("MyCMD Java Shell v1.0"); + } - @Override - public String description() { - return "Display the version information of the MyCMD shell."; - } + @Override + public String description() { + return "Display the version information of the MyCMD shell."; + } - @Override - public String usage() { - return "ver"; - } + @Override + public String usage() { + return "ver"; + } } diff --git a/src/main/java/com/mycmd/commands/VolCommand.java b/src/main/java/com/mycmd/commands/VolCommand.java index d83bbb6..f0bc5aa 100644 --- a/src/main/java/com/mycmd/commands/VolCommand.java +++ b/src/main/java/com/mycmd/commands/VolCommand.java @@ -12,49 +12,49 @@ */ public class VolCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - File drive; - - if (args.length == 0) { - drive = context.getCurrentDir(); - } else { - String drivePath = args[0]; - if (!drivePath.endsWith("\\") && !drivePath.endsWith("/")) { - drivePath += "\\"; - } - drive = new File(drivePath); - } - - if (!drive.exists()) { - System.out.println("The system cannot find the drive specified."); - return; - } - - // Get drive letter - String path = drive.getAbsolutePath(); - String driveLetter = path.substring(0, Math.min(2, path.length())); - - System.out.println(" Volume in drive " + driveLetter + " has no label."); - System.out.println(" Volume Serial Number is " + getSerialNumber(drive)); + @Override + public void execute(String[] args, ShellContext context) throws IOException { + File drive; + + if (args.length == 0) { + drive = context.getCurrentDir(); + } else { + String drivePath = args[0]; + if (!drivePath.endsWith("\\") && !drivePath.endsWith("/")) { + drivePath += "\\"; + } + drive = new File(drivePath); } - private String getSerialNumber(File drive) { - // Generate a pseudo-serial based on drive properties - long totalSpace = drive.getTotalSpace(); - long freeSpace = drive.getFreeSpace(); - long combined = totalSpace ^ freeSpace; - return String.format( - "%04X-%04X", (int) ((combined >>> 16) & 0xFFFF), (int) (combined & 0xFFFF)); + if (!drive.exists()) { + System.out.println("The system cannot find the drive specified."); + return; } - @Override - public String description() { - return "Display the disk volume label and serial number."; - } - - @Override - public String usage() { - return "vol [drive:]"; - } + // Get drive letter + String path = drive.getAbsolutePath(); + String driveLetter = path.substring(0, Math.min(2, path.length())); + + System.out.println(" Volume in drive " + driveLetter + " has no label."); + System.out.println(" Volume Serial Number is " + getSerialNumber(drive)); + } + + private String getSerialNumber(File drive) { + // Generate a pseudo-serial based on drive properties + long totalSpace = drive.getTotalSpace(); + long freeSpace = drive.getFreeSpace(); + long combined = totalSpace ^ freeSpace; + return String.format( + "%04X-%04X", (int) ((combined >>> 16) & 0xFFFF), (int) (combined & 0xFFFF)); + } + + @Override + public String description() { + return "Display the disk volume label and serial number."; + } + + @Override + public String usage() { + return "vol [drive:]"; + } } diff --git a/src/main/java/com/mycmd/commands/WhoamiCommand.java b/src/main/java/com/mycmd/commands/WhoamiCommand.java index 1a139de..bc972e7 100644 --- a/src/main/java/com/mycmd/commands/WhoamiCommand.java +++ b/src/main/java/com/mycmd/commands/WhoamiCommand.java @@ -15,18 +15,18 @@ * as reported by the Java runtime. */ public class WhoamiCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) { - System.out.println(System.getProperty("user.name")); - } + @Override + public void execute(String[] args, ShellContext context) { + System.out.println(System.getProperty("user.name")); + } - @Override - public String description() { - return "Display the username of logged in user"; - } + @Override + public String description() { + return "Display the username of logged in user"; + } - @Override - public String usage() { - return "whoami"; - } + @Override + public String usage() { + return "whoami"; + } } diff --git a/src/main/java/com/mycmd/commands/WmicCommand.java b/src/main/java/com/mycmd/commands/WmicCommand.java index 6438497..56a0247 100644 --- a/src/main/java/com/mycmd/commands/WmicCommand.java +++ b/src/main/java/com/mycmd/commands/WmicCommand.java @@ -14,61 +14,60 @@ */ public class WmicCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("WMIC - Windows Management Instrumentation Command-line"); - System.out.println("Usage: wmic [global switches] "); - System.out.println("\nCommon commands:"); - System.out.println(" wmic cpu get name"); - System.out.println(" wmic bios get serialnumber"); - System.out.println(" wmic os get caption"); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("WMIC - Windows Management Instrumentation Command-line"); + System.out.println("Usage: wmic [global switches] "); + System.out.println("\nCommon commands:"); + System.out.println(" wmic cpu get name"); + System.out.println(" wmic bios get serialnumber"); + System.out.println(" wmic os get caption"); + return; + } - // Check if wmic is available on the system - String os = System.getProperty("os.name").toLowerCase(); - if (!os.contains("win")) { - System.out.println("WMIC is only available on Windows systems."); - return; - } + // Check if wmic is available on the system + String os = System.getProperty("os.name").toLowerCase(); + if (!os.contains("win")) { + System.out.println("WMIC is only available on Windows systems."); + return; + } - try { - // Build the wmic command - StringBuilder cmdBuilder = new StringBuilder("wmic"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); - } + try { + // Build the wmic command + StringBuilder cmdBuilder = new StringBuilder("wmic"); + for (String arg : args) { + cmdBuilder.append(" ").append(arg); + } - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing WMIC command: " + e.getMessage()); - } + } catch (Exception e) { + System.out.println("Error executing WMIC command: " + e.getMessage()); } + } - @Override - public String description() { - return "Windows Management Instrumentation Command-line interface."; - } + @Override + public String description() { + return "Windows Management Instrumentation Command-line interface."; + } - @Override - public String usage() { - return "wmic [query]"; - } + @Override + public String usage() { + return "wmic [query]"; + } } diff --git a/src/main/java/com/mycmd/commands/XcopyCommand.java b/src/main/java/com/mycmd/commands/XcopyCommand.java index 0eb0729..4dc9149 100644 --- a/src/main/java/com/mycmd/commands/XcopyCommand.java +++ b/src/main/java/com/mycmd/commands/XcopyCommand.java @@ -13,69 +13,68 @@ */ public class XcopyCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length == 0) { - System.out.println("Copies files and directory trees."); - System.out.println("\nXCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]]"); - System.out.println(" [/V] [/W] [/C] [/I] [/Q] [/F] [/L]"); - System.out.println(" [/H] [/R] [/T] [/U] [/K] [/N] [/O]"); - System.out.println(" [/X] [/Y] [/-Y] [/Z] [/B]"); - System.out.println( - "\n /S Copies directories and subdirectories except empty ones."); - System.out.println( - " /E Copies directories and subdirectories, including empty ones."); - System.out.println(" /Y Suppresses prompting to confirm overwriting."); - System.out.println( - " /I If destination does not exist and copying more than one file,"); - System.out.println(" assumes that destination must be a directory."); - return; - } + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Copies files and directory trees."); + System.out.println("\nXCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]]"); + System.out.println(" [/V] [/W] [/C] [/I] [/Q] [/F] [/L]"); + System.out.println(" [/H] [/R] [/T] [/U] [/K] [/N] [/O]"); + System.out.println(" [/X] [/Y] [/-Y] [/Z] [/B]"); + System.out.println( + "\n /S Copies directories and subdirectories except empty ones."); + System.out.println( + " /E Copies directories and subdirectories, including empty ones."); + System.out.println(" /Y Suppresses prompting to confirm overwriting."); + System.out.println( + " /I If destination does not exist and copying more than one file,"); + System.out.println(" assumes that destination must be a directory."); + return; + } - String os = System.getProperty("os.name").toLowerCase(); + String os = System.getProperty("os.name").toLowerCase(); - if (os.contains("win")) { - try { - StringBuilder cmdBuilder = new StringBuilder("xcopy"); - for (String arg : args) { - cmdBuilder.append(" \"").append(arg).append("\""); - } + if (os.contains("win")) { + try { + StringBuilder cmdBuilder = new StringBuilder("xcopy"); + for (String arg : args) { + cmdBuilder.append(" \"").append(arg).append("\""); + } - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); - pb.directory(context.getCurrentDir()); - Process process = pb.start(); + ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", cmdBuilder.toString()); + pb.directory(context.getCurrentDir()); + Process process = pb.start(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream())); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - process.waitFor(); + process.waitFor(); - } catch (Exception e) { - System.out.println("Error executing xcopy: " + e.getMessage()); - } - } else { - System.out.println("XCOPY is not available on this system. Use 'cp -r' instead."); - } + } catch (Exception e) { + System.out.println("Error executing xcopy: " + e.getMessage()); + } + } else { + System.out.println("XCOPY is not available on this system. Use 'cp -r' instead."); } + } - @Override - public String description() { - return "Copies files and directory trees."; - } + @Override + public String description() { + return "Copies files and directory trees."; + } - @Override - public String usage() { - return "xcopy source [destination] [/S] [/E] [/Y]"; - } + @Override + public String usage() { + return "xcopy source [destination] [/S] [/E] [/Y]"; + } } diff --git a/src/main/java/com/mycmd/gui/MainApp.java b/src/main/java/com/mycmd/gui/MainApp.java index 60f3867..faaee80 100644 --- a/src/main/java/com/mycmd/gui/MainApp.java +++ b/src/main/java/com/mycmd/gui/MainApp.java @@ -7,50 +7,45 @@ import javafx.scene.image.Image; import javafx.stage.Stage; -/** - * JavaFX entry point โ€” futuristic terminal window for MyCMD. - */ +/** JavaFX entry point โ€” futuristic terminal window for MyCMD. */ public class MainApp extends Application { - private static ShellEngine engine; - private static ShellContext context; - private static CommandRegistry registry; - - @Override - public void start(Stage stage) throws Exception { - // initialize core shell - context = new ShellContext(); - registry = new CommandRegistry(); - engine = new ShellEngine(registry, context); - - // register built-in commands (auto load) - registerBuiltIns(); - - FXMLLoader loader = new FXMLLoader( - getClass().getResource("/com/mycmd/gui/terminal.fxml")); - Scene scene = new Scene(loader.load()); - scene.getStylesheets().add( - getClass().getResource("/com/mycmd/gui/style.css").toExternalForm()); - - TerminalController controller = loader.getController(); - controller.init(engine, context); - - stage.setTitle("MyCMD โ–‘โ–“ Java Terminal โ–“โ–‘"); - stage.getIcons().add( - new Image(getClass().getResourceAsStream("/com/mycmd/gui/icon.png"))); - stage.setScene(scene); - stage.setResizable(false); - stage.show(); - } - - private void registerBuiltIns() { - registry.register("alias", new com.mycmd.commands.AliasCommand()); - registry.register("dir", new com.mycmd.commands.DirCommand()); - registry.register("echo", new com.mycmd.commands.EchoCommand()); - // add others automatically here as you expand - } - - public static void main(String[] args) { - launch(); - } + private static ShellEngine engine; + private static ShellContext context; + private static CommandRegistry registry; + + @Override + public void start(Stage stage) throws Exception { + // initialize core shell + context = new ShellContext(); + registry = new CommandRegistry(); + engine = new ShellEngine(registry, context); + + // register built-in commands (auto load) + registerBuiltIns(); + + FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/mycmd/gui/terminal.fxml")); + Scene scene = new Scene(loader.load()); + scene.getStylesheets().add(getClass().getResource("/com/mycmd/gui/style.css").toExternalForm()); + + TerminalController controller = loader.getController(); + controller.init(engine, context); + + stage.setTitle("MyCMD โ–‘โ–“ Java Terminal โ–“โ–‘"); + stage.getIcons().add(new Image(getClass().getResourceAsStream("/com/mycmd/gui/icon.png"))); + stage.setScene(scene); + stage.setResizable(false); + stage.show(); + } + + private void registerBuiltIns() { + registry.register("alias", new com.mycmd.commands.AliasCommand()); + registry.register("dir", new com.mycmd.commands.DirCommand()); + registry.register("echo", new com.mycmd.commands.EchoCommand()); + // add others automatically here as you expand + } + + public static void main(String[] args) { + launch(); + } } diff --git a/src/main/java/com/mycmd/gui/TerminalController.java b/src/main/java/com/mycmd/gui/TerminalController.java index 6ab93b3..a1e93d3 100644 --- a/src/main/java/com/mycmd/gui/TerminalController.java +++ b/src/main/java/com/mycmd/gui/TerminalController.java @@ -8,37 +8,36 @@ import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; -/** - * Controller for the FXML terminal. - */ +/** Controller for the FXML terminal. */ public class TerminalController { - @FXML private TextArea outputArea; - @FXML private TextField inputField; - @FXML private ScrollPane scrollPane; - - private ShellEngine engine; - private ShellContext context; - - public void init(ShellEngine engine, ShellContext context) { - this.engine = engine; - this.context = context; - - output("๐Ÿ’ป Welcome to MyCMD - Java made Terminal"); - output("Type 'help' for available commands.\n"); - - inputField.setOnKeyPressed(event -> { - if (event.getCode() == KeyCode.ENTER) { - String input = inputField.getText(); - inputField.clear(); - output("> " + input); - engine.execute(input); - scrollPane.setVvalue(1.0); - } + @FXML private TextArea outputArea; + @FXML private TextField inputField; + @FXML private ScrollPane scrollPane; + + private ShellEngine engine; + private ShellContext context; + + public void init(ShellEngine engine, ShellContext context) { + this.engine = engine; + this.context = context; + + output("๐Ÿ’ป Welcome to MyCMD - Java made Terminal"); + output("Type 'help' for available commands.\n"); + + inputField.setOnKeyPressed( + event -> { + if (event.getCode() == KeyCode.ENTER) { + String input = inputField.getText(); + inputField.clear(); + output("> " + input); + engine.execute(input); + scrollPane.setVvalue(1.0); + } }); - } + } - private void output(String text) { - outputArea.appendText(text + "\n"); - } + private void output(String text) { + outputArea.appendText(text + "\n"); + } } From e000143352b9e7e8b927978e604a5ac6ee22552e Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Tue, 11 Nov 2025 15:18:11 +0530 Subject: [PATCH 05/42] Refactor AssocCommand to use ProcessBuilder Refactor command execution to use ProcessBuilder for better error handling and timeout management. --- .../java/com/mycmd/commands/AssocCommand.java | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/mycmd/commands/AssocCommand.java b/src/main/java/com/mycmd/commands/AssocCommand.java index e2bced4..e8a4af9 100644 --- a/src/main/java/com/mycmd/commands/AssocCommand.java +++ b/src/main/java/com/mycmd/commands/AssocCommand.java @@ -5,6 +5,10 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; /** * Displays or modifies file extension associations. @@ -23,20 +27,65 @@ public void execute(String[] args, ShellContext context) throws IOException { } try { - StringBuilder cmdBuilder = new StringBuilder("assoc"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); + + List command = new ArrayList<>(); + command.add("cmd.exe"); + command.add("/c"); + command.add("assoc"); + if (args != null && args.length > 0) { + command.addAll(Arrays.asList(args)); + } + + ProcessBuilder pb = new ProcessBuilder(command); + Process process = pb.start(); + + Thread errorGobbler = + new Thread( + () -> { + try (BufferedReader errReader = + new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String errLine; + while ((errLine = errReader.readLine()) != null) { + System.err.println(errLine); + } + } catch (IOException e) { + + System.err.println("Error reading process error stream: " + e.getMessage()); + } + }, + "assoc-error-gobbler"); + errorGobbler.setDaemon(true); + errorGobbler.start(); + + + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } } - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + boolean finished; + try { + finished = process.waitFor(30, TimeUnit.SECONDS); + } catch (InterruptedException ie) { - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); + Thread.currentThread().interrupt(); + process.destroyForcibly(); + throw new IOException("Interrupted while waiting for assoc process", ie); } - process.waitFor(); + if (!finished) { + process.destroyForcibly(); + System.out.println("Command timed out."); + } + + try { + errorGobbler.join(1000); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } } catch (Exception e) { System.out.println("Error executing assoc: " + e.getMessage()); From b160eb05ae64ddccd9f810881a454a5911512606 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 09:48:25 +0000 Subject: [PATCH 06/42] Apply Spotless formatting --- src/main/java/com/mycmd/commands/AssocCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/mycmd/commands/AssocCommand.java b/src/main/java/com/mycmd/commands/AssocCommand.java index e8a4af9..331978f 100644 --- a/src/main/java/com/mycmd/commands/AssocCommand.java +++ b/src/main/java/com/mycmd/commands/AssocCommand.java @@ -57,7 +57,6 @@ public void execute(String[] args, ShellContext context) throws IOException { errorGobbler.setDaemon(true); errorGobbler.start(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { String line; From a9bff0909c262a289fd11792e024e4b16d2e3529 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Tue, 11 Nov 2025 15:27:08 +0530 Subject: [PATCH 07/42] Refactor DriverqueryCommand for better process handling Refactor DriverqueryCommand to use ProcessBuilder for command execution and add error handling with a dedicated thread for error stream. --- .../mycmd/commands/DriverqueryCommand.java | 70 ++++++++++++++++--- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/mycmd/commands/DriverqueryCommand.java b/src/main/java/com/mycmd/commands/DriverqueryCommand.java index 03769cd..faef190 100644 --- a/src/main/java/com/mycmd/commands/DriverqueryCommand.java +++ b/src/main/java/com/mycmd/commands/DriverqueryCommand.java @@ -5,6 +5,10 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; /** * Displays a list of all installed device drivers. @@ -23,22 +27,66 @@ public void execute(String[] args, ShellContext context) throws IOException { } try { - StringBuilder cmdBuilder = new StringBuilder("driverquery"); - for (String arg : args) { - cmdBuilder.append(" ").append(arg); + + List command = new ArrayList<>(); + command.add("cmd.exe"); + command.add("/c"); + command.add("driverquery"); + if (args != null && args.length > 0) { + command.addAll(Arrays.asList(args)); + } + + ProcessBuilder pb = new ProcessBuilder(command); + Process process = pb.start(); + + Thread errorGobbler = + new Thread( + () -> { + try (BufferedReader errReader = + new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String errLine; + while ((errLine = errReader.readLine()) != null) { + System.err.println(errLine); + } + } catch (IOException e) { + System.err.println("Error reading process error stream: " + e.getMessage()); + } + }, + "driverquery-error-gobbler"); + errorGobbler.setDaemon(true); + errorGobbler.start(); + + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } } - Process process = Runtime.getRuntime().exec(cmdBuilder.toString()); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + boolean finished; + try { + finished = process.waitFor(30, TimeUnit.SECONDS); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + process.destroyForcibly(); + throw new IOException("Interrupted while waiting for driverquery process", ie); + } - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); + if (!finished) { + process.destroyForcibly(); + System.out.println("Command timed out."); + } else { + int exitCode = process.exitValue(); + if (exitCode != 0) { + System.out.println("Command exited with code: " + exitCode); + } } - int exitCode = process.waitFor(); - if (exitCode != 0) { - System.out.println("Command exited with code: " + exitCode); + try { + errorGobbler.join(1000); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); } } catch (Exception e) { From 85365e70b1511b8223b7c9d63843758dd77b35f8 Mon Sep 17 00:00:00 2001 From: Anshuman Jadiya Date: Tue, 11 Nov 2025 15:32:58 +0530 Subject: [PATCH 08/42] Refactor DriverqueryCommand to simplify command list Removed unnecessary command execution for cmd.exe. --- src/main/java/com/mycmd/commands/DriverqueryCommand.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/mycmd/commands/DriverqueryCommand.java b/src/main/java/com/mycmd/commands/DriverqueryCommand.java index faef190..c9ce2d0 100644 --- a/src/main/java/com/mycmd/commands/DriverqueryCommand.java +++ b/src/main/java/com/mycmd/commands/DriverqueryCommand.java @@ -29,8 +29,6 @@ public void execute(String[] args, ShellContext context) throws IOException { try { List command = new ArrayList<>(); - command.add("cmd.exe"); - command.add("/c"); command.add("driverquery"); if (args != null && args.length > 0) { command.addAll(Arrays.asList(args)); From 1e31910198738e3ca2c59445c8c4dfa51bef9251 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:22:38 +0100 Subject: [PATCH 09/42] Update ShellContext.java --- src/main/java/com/mycmd/ShellContext.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index 8bac1d3..d833b00 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -3,6 +3,7 @@ import java.io.File; import java.util.HashMap; import java.util.Map; +import java.util.Scanner; public class ShellContext { From 4b5a9caba16f2f91f47778a9c171bab90b1ad210 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:38:54 +0100 Subject: [PATCH 10/42] Refactor: Update FcCommand.java --- src/main/java/com/mycmd/commands/FcCommand.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/mycmd/commands/FcCommand.java b/src/main/java/com/mycmd/commands/FcCommand.java index 4a3139e..ca61072 100644 --- a/src/main/java/com/mycmd/commands/FcCommand.java +++ b/src/main/java/com/mycmd/commands/FcCommand.java @@ -17,13 +17,11 @@ public class FcCommand implements Command { public void execute(String[] args, ShellContext context) throws IOException { if (args.length < 2) { System.out.println("Compares two files or sets of files and displays the differences."); - System.out.println("\nFC [/A] [/B] [/C] [/L] [/LBn] [/N] [/T] [/W] [/nnnn]"); + System.out.println("\nFC [/B] [/C] [/N]"); System.out.println(" [drive1:][path1]filename1 [drive2:][path2]filename2"); - System.out.println( - "\n /A Displays only first and last lines for each set of differences."); + System.out.println(""); System.out.println(" /B Performs a binary comparison."); System.out.println(" /C Disregards the case of letters."); - System.out.println(" /L Compares files as ASCII text."); System.out.println(" /N Displays the line numbers on an ASCII comparison."); return; } From e23aebf771c0a2bbdfcb64c13a336c83a1ef6b44 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:45:32 +0100 Subject: [PATCH 11/42] Refactor: Update PathCommand.java --- src/main/java/com/mycmd/commands/PathCommand.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mycmd/commands/PathCommand.java b/src/main/java/com/mycmd/commands/PathCommand.java index bff2c21..bbc3ca6 100644 --- a/src/main/java/com/mycmd/commands/PathCommand.java +++ b/src/main/java/com/mycmd/commands/PathCommand.java @@ -15,7 +15,11 @@ public class PathCommand implements Command { public void execute(String[] args, ShellContext context) throws IOException { if (args.length == 0) { // Display current PATH - String path = System.getenv("PATH"); + String path = context.getEnvVar("PATH"); + if (path == null || path.isEmpty()) { + path = System.getenv("PATH"); + } + if (path != null) { System.out.println("PATH=" + path); } else { @@ -31,8 +35,10 @@ public void execute(String[] args, ShellContext context) throws IOException { String newPath = String.join(" ", args); if (newPath.equalsIgnoreCase(";")) { + context.setEnvVar("PATH", ""); System.out.println("PATH cleared (session only)"); } else { + context.setEnvVar("PATH", newPath); System.out.println("PATH set to: " + newPath + " (session only)"); } } From 3b9abd418ee845dba05cafea96560bb841c2baf9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 10:45:47 +0000 Subject: [PATCH 12/42] Apply Spotless formatting --- src/main/java/com/mycmd/commands/PathCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mycmd/commands/PathCommand.java b/src/main/java/com/mycmd/commands/PathCommand.java index bbc3ca6..20f9aca 100644 --- a/src/main/java/com/mycmd/commands/PathCommand.java +++ b/src/main/java/com/mycmd/commands/PathCommand.java @@ -19,7 +19,7 @@ public void execute(String[] args, ShellContext context) throws IOException { if (path == null || path.isEmpty()) { path = System.getenv("PATH"); } - + if (path != null) { System.out.println("PATH=" + path); } else { From b598a37ff4290c70f2ea955b497f6b97aec4dbce Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:49:08 +0100 Subject: [PATCH 13/42] Refactor: Update PingCommand.java --- .../java/com/mycmd/commands/PingCommand.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mycmd/commands/PingCommand.java b/src/main/java/com/mycmd/commands/PingCommand.java index 7e892b6..10b598f 100644 --- a/src/main/java/com/mycmd/commands/PingCommand.java +++ b/src/main/java/com/mycmd/commands/PingCommand.java @@ -64,7 +64,27 @@ public void execute(String[] args, ShellContext context) throws IOException { return; } - String host = args[0]; + int hostIndex = -1; + for (int i = 0; i < args.length; i++) { + if (!args[i].startsWith("-")) { + hostIndex = i; + break; + } + // Skip option payload when present + if ((args[i].equalsIgnoreCase("-n") + || args[i].equalsIgnoreCase("-c") + || args[i].equalsIgnoreCase("-w") + || args[i].equalsIgnoreCase("-l") + || args[i].equalsIgnoreCase("-i")) + && i + 1 < args.length) { + i++; + } + } + if (hostIndex == -1) { + System.out.println("Error: target host is required."); + return; + } + String host = args[hostIndex]; // Validate hostname/IP if (!validateHost(host)) { From 56d0488304df5615e335b3d5552b5e114c7823ef Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 10:49:26 +0000 Subject: [PATCH 14/42] Apply Spotless formatting --- src/main/java/com/mycmd/commands/PingCommand.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/mycmd/commands/PingCommand.java b/src/main/java/com/mycmd/commands/PingCommand.java index 10b598f..5d68277 100644 --- a/src/main/java/com/mycmd/commands/PingCommand.java +++ b/src/main/java/com/mycmd/commands/PingCommand.java @@ -72,13 +72,13 @@ public void execute(String[] args, ShellContext context) throws IOException { } // Skip option payload when present if ((args[i].equalsIgnoreCase("-n") - || args[i].equalsIgnoreCase("-c") - || args[i].equalsIgnoreCase("-w") - || args[i].equalsIgnoreCase("-l") - || args[i].equalsIgnoreCase("-i")) - && i + 1 < args.length) { - i++; - } + || args[i].equalsIgnoreCase("-c") + || args[i].equalsIgnoreCase("-w") + || args[i].equalsIgnoreCase("-l") + || args[i].equalsIgnoreCase("-i")) + && i + 1 < args.length) { + i++; + } } if (hostIndex == -1) { System.out.println("Error: target host is required."); From e868dbefed2e5bd23c6f17b248454aa8deaecd89 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:50:50 +0100 Subject: [PATCH 15/42] Refactor: 2nd Update PingCommand.java --- src/main/java/com/mycmd/commands/PingCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mycmd/commands/PingCommand.java b/src/main/java/com/mycmd/commands/PingCommand.java index 5d68277..5a13a14 100644 --- a/src/main/java/com/mycmd/commands/PingCommand.java +++ b/src/main/java/com/mycmd/commands/PingCommand.java @@ -145,7 +145,7 @@ private boolean validateHost(String host) { // Basic validation - allow alphanumeric, dots, hyphens for hostnames // More complex validation will happen during resolution - return host.matches("^[a-zA-Z0-9.-]+$"); + return host.matches("^[a-zA-Z0-9._:-]+$"); } /** Resolves hostname to IP address. */ From b3d751d007afcb37aaab9ac6611aacc4765852bb Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:55:56 +0100 Subject: [PATCH 16/42] Refactor: Update ShutdownCommand.java --- .../com/mycmd/commands/ShutdownCommand.java | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index 815d920..3c5e05c 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -5,6 +5,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; /** * Shuts down or restarts the computer. @@ -37,12 +38,13 @@ public void execute(String[] args, ShellContext context) throws IOException { System.out.println("WARNING: This will execute a real shutdown command!"); System.out.print("Are you sure you want to continue? (yes/no): "); - java.util.Scanner scanner = new java.util.Scanner(System.in); - String confirmation = scanner.nextLine().trim().toLowerCase(); - - if (!confirmation.equals("yes")) { - System.out.println("Shutdown cancelled."); - return; + try (java.util.Scanner scanner = new java.util.Scanner(System.in)) { + String confirmation = scanner.nextLine().trim().toLowerCase(); + if (!confirmation.equals("yes")) { + System.out.println("Shutdown cancelled."); + return; + } + } } try { @@ -61,21 +63,15 @@ public void execute(String[] args, ShellContext context) throws IOException { } Process process = pb.start(); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + try (java.util.Scanner scanner = new java.util.Scanner(System.in)) { + String confirmation = scanner.nextLine().trim().toLowerCase(); - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); + if (!confirmation.equals("yes")) { + System.out.println("Shutdown cancelled."); + return; + } } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } - - process.waitFor(); - } catch (Exception e) { System.out.println("Error executing shutdown: " + e.getMessage()); System.out.println("Administrator privileges may be required."); From 81073b571259c97ff460aef758f10631b4bbff19 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:57:19 +0100 Subject: [PATCH 17/42] Refactor: Update TelnetCommand.java --- src/main/java/com/mycmd/commands/TelnetCommand.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/com/mycmd/commands/TelnetCommand.java b/src/main/java/com/mycmd/commands/TelnetCommand.java index 72ad891..a1ae5e8 100644 --- a/src/main/java/com/mycmd/commands/TelnetCommand.java +++ b/src/main/java/com/mycmd/commands/TelnetCommand.java @@ -73,13 +73,6 @@ public void execute(String[] args, ShellContext context) throws IOException { } catch (IOException ignored) { // stdin/socket error, will disconnect } - - // ensure socket closes to stop reader - try { - socket.close(); - } catch (IOException ignored) { - } - System.out.println("\nDisconnected."); } catch (IOException e) { System.out.println("Connection failed: " + e.getMessage()); } From b093d0e1fca4dcf100c289c7449973af44dd7ab6 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:15:17 +0100 Subject: [PATCH 18/42] Refactor: Update RouteCommand.java --- .../java/com/mycmd/commands/RouteCommand.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/mycmd/commands/RouteCommand.java b/src/main/java/com/mycmd/commands/RouteCommand.java index 237df7d..87dcff6 100644 --- a/src/main/java/com/mycmd/commands/RouteCommand.java +++ b/src/main/java/com/mycmd/commands/RouteCommand.java @@ -5,6 +5,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; /** * Displays and modifies entries in the local IP routing table. @@ -45,20 +46,22 @@ public void execute(String[] args, ShellContext context) throws IOException { } Process process = pb.start(); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream())); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } - - process.waitFor(); + if (!process.waitFor(30, TimeUnit.SECONDS)) { + process.destroyForcibly(); + System.out.println("Command timed out."); + } } catch (Exception e) { System.out.println("Error executing route: " + e.getMessage()); From eef7d7e279b3983a46675f081df7d34833d704cd Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:15:27 +0100 Subject: [PATCH 19/42] Refactor: 2nd Update ShutdownCommand.java --- .../com/mycmd/commands/ShutdownCommand.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index 3c5e05c..c45cebd 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -44,8 +44,8 @@ public void execute(String[] args, ShellContext context) throws IOException { System.out.println("Shutdown cancelled."); return; } - } } + } try { StringBuilder cmdBuilder = new StringBuilder("shutdown"); @@ -63,15 +63,23 @@ public void execute(String[] args, ShellContext context) throws IOException { } Process process = pb.start(); - try (java.util.Scanner scanner = new java.util.Scanner(System.in)) { - String confirmation = scanner.nextLine().trim().toLowerCase(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - if (!confirmation.equals("yes")) { - System.out.println("Shutdown cancelled."); - return; + while ((line = errorReader.readLine()) != null) { + System.err.println(line); } } + if (!process.waitFor(30, TimeUnit.SECONDS)) { + process.destroyForcibly(); + System.out.println("Command timed out."); + } + } catch (Exception e) { System.out.println("Error executing shutdown: " + e.getMessage()); System.out.println("Administrator privileges may be required."); From f9db5f187e89af3af5a045c0010bf27dae21ce7c Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:20:52 +0100 Subject: [PATCH 20/42] Refactor: 3rd Update PathCommand.java --- src/main/java/com/mycmd/commands/PathCommand.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mycmd/commands/PathCommand.java b/src/main/java/com/mycmd/commands/PathCommand.java index 20f9aca..7e2e91c 100644 --- a/src/main/java/com/mycmd/commands/PathCommand.java +++ b/src/main/java/com/mycmd/commands/PathCommand.java @@ -16,12 +16,16 @@ public void execute(String[] args, ShellContext context) throws IOException { if (args.length == 0) { // Display current PATH String path = context.getEnvVar("PATH"); - if (path == null || path.isEmpty()) { + if (path == null) { path = System.getenv("PATH"); } if (path != null) { - System.out.println("PATH=" + path); + if (path.isEmpty()) { + System.out.println("PATH is cleared (session only)"); + } else { + System.out.println("PATH=" + path); + } } else { System.out.println("No Path"); } From 1e5c46b41873cd96167587c5871ee04d91890fcd Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:25:21 +0100 Subject: [PATCH 21/42] Refactor : 3rd Update ShutdownCommand.java --- src/main/java/com/mycmd/commands/ShutdownCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index c45cebd..a474b37 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -45,7 +45,7 @@ public void execute(String[] args, ShellContext context) throws IOException { return; } } - } + try { StringBuilder cmdBuilder = new StringBuilder("shutdown"); From 00938d3f676b82fb5e479db850544328967a2945 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 12:25:40 +0000 Subject: [PATCH 22/42] Apply Spotless formatting --- .../java/com/mycmd/commands/RouteCommand.java | 26 ++++++++++--------- .../com/mycmd/commands/ShutdownCommand.java | 7 ++--- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/mycmd/commands/RouteCommand.java b/src/main/java/com/mycmd/commands/RouteCommand.java index 87dcff6..46ac477 100644 --- a/src/main/java/com/mycmd/commands/RouteCommand.java +++ b/src/main/java/com/mycmd/commands/RouteCommand.java @@ -46,22 +46,24 @@ public void execute(String[] args, ShellContext context) throws IOException { } Process process = pb.start(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream()))) { String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } + while ((line = reader.readLine()) != null) { + System.out.println(line); + } - while ((line = errorReader.readLine()) != null) { - System.err.println(line); - } + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } } - if (!process.waitFor(30, TimeUnit.SECONDS)) { - process.destroyForcibly(); - System.out.println("Command timed out."); - } + if (!process.waitFor(30, TimeUnit.SECONDS)) { + process.destroyForcibly(); + System.out.println("Command timed out."); + } } catch (Exception e) { System.out.println("Error executing route: " + e.getMessage()); diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index a474b37..33da114 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -45,7 +45,6 @@ public void execute(String[] args, ShellContext context) throws IOException { return; } } - try { StringBuilder cmdBuilder = new StringBuilder("shutdown"); @@ -63,8 +62,10 @@ public void execute(String[] args, ShellContext context) throws IOException { } Process process = pb.start(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream())); + BufferedReader errorReader = + new BufferedReader(new InputStreamReader(process.getErrorStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); From 065cab680b6449dfbf2dafbd2d7a3c98276c760a Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:26:52 +0100 Subject: [PATCH 23/42] Refactor : 3rd Update TelnetCommand.java --- src/main/java/com/mycmd/commands/TelnetCommand.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/mycmd/commands/TelnetCommand.java b/src/main/java/com/mycmd/commands/TelnetCommand.java index a1ae5e8..88e65f4 100644 --- a/src/main/java/com/mycmd/commands/TelnetCommand.java +++ b/src/main/java/com/mycmd/commands/TelnetCommand.java @@ -76,6 +76,12 @@ public void execute(String[] args, ShellContext context) throws IOException { } catch (IOException e) { System.out.println("Connection failed: " + e.getMessage()); } + + try { + reader.join(1000); // wait up to 1 second for reader to finish + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } @Override From a68b03c9341fd5a433f6afff35180ee576660d06 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:40:21 +0100 Subject: [PATCH 24/42] Refactorise Update ShutdownCommand.java to accomodate suggested changes. --- .../com/mycmd/commands/ShutdownCommand.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index 33da114..6f1f426 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -59,22 +59,38 @@ public void execute(String[] args, ShellContext context) throws IOException { pb.command("cmd.exe", "/c", cmdBuilder.toString()); } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) { pb.command("sh", "-c", cmdBuilder.toString()); - } + } else { + System.out.println("Unsupported operating system: " + os); + return; + } Process process = pb.start(); - try (BufferedReader reader = - new BufferedReader(new InputStreamReader(process.getInputStream())); - BufferedReader errorReader = - new BufferedReader(new InputStreamReader(process.getErrorStream()))) { - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); + Thread outputThread = new Thread(() -> { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + } catch (IOException e) { + System.err.println("Error reading output: " + e.getMessage()); } - - while ((line = errorReader.readLine()) != null) { - System.err.println(line); + }); + + Thread errorThread = new Thread(() -> { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.err.println(line); + } + } catch (IOException e) { + System.err.println("Error reading error stream: " + e.getMessage()); } - } + }); + + outputThread.start(); + errorThread.start(); + outputThread.join(); + errorThread.join(); if (!process.waitFor(30, TimeUnit.SECONDS)) { process.destroyForcibly(); From ef2c9952dae02dc2fb2f5194bf9b08ed57c87983 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 12:40:35 +0000 Subject: [PATCH 25/42] Apply Spotless formatting --- .../com/mycmd/commands/ShutdownCommand.java | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index 6f1f426..f10e8f0 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -62,31 +62,37 @@ public void execute(String[] args, ShellContext context) throws IOException { } else { System.out.println("Unsupported operating system: " + os); return; - } + } Process process = pb.start(); - Thread outputThread = new Thread(() -> { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String line; - while ((line = reader.readLine()) != null) { - System.out.println(line); - } - } catch (IOException e) { - System.err.println("Error reading output: " + e.getMessage()); - } - }); - - Thread errorThread = new Thread(() -> { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { - String line; - while ((line = reader.readLine()) != null) { - System.err.println(line); - } - } catch (IOException e) { - System.err.println("Error reading error stream: " + e.getMessage()); - } - }); - + Thread outputThread = + new Thread( + () -> { + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + } catch (IOException e) { + System.err.println("Error reading output: " + e.getMessage()); + } + }); + + Thread errorThread = + new Thread( + () -> { + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(process.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.err.println(line); + } + } catch (IOException e) { + System.err.println("Error reading error stream: " + e.getMessage()); + } + }); + outputThread.start(); errorThread.start(); outputThread.join(); From f993d7cfe724338c9d8feb612466966bde71cb06 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:07:44 +0100 Subject: [PATCH 26/42] Refactorization to Update TelnetCommand.java --- src/main/java/com/mycmd/commands/TelnetCommand.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/mycmd/commands/TelnetCommand.java b/src/main/java/com/mycmd/commands/TelnetCommand.java index 88e65f4..9c6a379 100644 --- a/src/main/java/com/mycmd/commands/TelnetCommand.java +++ b/src/main/java/com/mycmd/commands/TelnetCommand.java @@ -31,12 +31,13 @@ public void execute(String[] args, ShellContext context) throws IOException { } } + Thread reader = null; try (Socket socket = new Socket(host, port)) { socket.setSoTimeout(0); // blocking reads System.out.println("Connected to " + host + ":" + port + " (type 'exit' to quit)"); // Reader thread: prints remote data to stdout - Thread reader = + reader = new Thread( () -> { try (InputStream in = socket.getInputStream(); @@ -77,10 +78,12 @@ public void execute(String[] args, ShellContext context) throws IOException { System.out.println("Connection failed: " + e.getMessage()); } - try { - reader.join(1000); // wait up to 1 second for reader to finish - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + if (reader != null) { + try { + reader.join(1000); // wait up to 1 second for reader to finish + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } } From eec483ab65ca2eeb2f6c76fec3cabdc012cb7714 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:10:50 +0100 Subject: [PATCH 27/42] Refactor : Update ShutdownCommand.java --- src/main/java/com/mycmd/commands/ShutdownCommand.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index f10e8f0..e57d076 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -95,13 +95,16 @@ public void execute(String[] args, ShellContext context) throws IOException { outputThread.start(); errorThread.start(); - outputThread.join(); - errorThread.join(); - - if (!process.waitFor(30, TimeUnit.SECONDS)) { + + boolean finished = process.waitFor(30, TimeUnit.SECONDS); + if (!finished) { process.destroyForcibly(); System.out.println("Command timed out."); + process.waitFor(); } + + outputThread.join(); + errorThread.join(); } catch (Exception e) { System.out.println("Error executing shutdown: " + e.getMessage()); From 912fd882bf4d490c9c34fdb534e2782190efec15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 13:11:05 +0000 Subject: [PATCH 28/42] Apply Spotless formatting --- src/main/java/com/mycmd/commands/ShutdownCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index e57d076..3e00db4 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -95,14 +95,14 @@ public void execute(String[] args, ShellContext context) throws IOException { outputThread.start(); errorThread.start(); - + boolean finished = process.waitFor(30, TimeUnit.SECONDS); if (!finished) { process.destroyForcibly(); System.out.println("Command timed out."); process.waitFor(); } - + outputThread.join(); errorThread.join(); From b455a2870d7ea33894d4e929bd95b4d787a79d7c Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:20:12 +0100 Subject: [PATCH 29/42] Refactor: Update TelnetCommand.java --- src/main/java/com/mycmd/commands/TelnetCommand.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/mycmd/commands/TelnetCommand.java b/src/main/java/com/mycmd/commands/TelnetCommand.java index 9c6a379..553c215 100644 --- a/src/main/java/com/mycmd/commands/TelnetCommand.java +++ b/src/main/java/com/mycmd/commands/TelnetCommand.java @@ -59,11 +59,10 @@ public void execute(String[] args, ShellContext context) throws IOException { reader.start(); // Writer loop: read stdin and send to remote + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); try (OutputStream out = socket.getOutputStream(); - OutputStreamWriter osw = new OutputStreamWriter(out); - BufferedWriter bw = new BufferedWriter(osw); - BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in))) { - + OutputStreamWriter osw = new OutputStreamWriter(out); + BufferedWriter bw = new BufferedWriter(osw)) { String line; while ((line = stdin.readLine()) != null) { if ("exit".equalsIgnoreCase(line.trim())) break; From d4ea8e777855b0936f8d3feb085aea7c19451af3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 13:20:36 +0000 Subject: [PATCH 30/42] Apply Spotless formatting --- src/main/java/com/mycmd/commands/TelnetCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mycmd/commands/TelnetCommand.java b/src/main/java/com/mycmd/commands/TelnetCommand.java index 553c215..73240c4 100644 --- a/src/main/java/com/mycmd/commands/TelnetCommand.java +++ b/src/main/java/com/mycmd/commands/TelnetCommand.java @@ -61,8 +61,8 @@ public void execute(String[] args, ShellContext context) throws IOException { // Writer loop: read stdin and send to remote BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); try (OutputStream out = socket.getOutputStream(); - OutputStreamWriter osw = new OutputStreamWriter(out); - BufferedWriter bw = new BufferedWriter(osw)) { + OutputStreamWriter osw = new OutputStreamWriter(out); + BufferedWriter bw = new BufferedWriter(osw)) { String line; while ((line = stdin.readLine()) != null) { if ("exit".equalsIgnoreCase(line.trim())) break; From c837e646137c0064986716b681e49211607cb414 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:21:52 +0100 Subject: [PATCH 31/42] Refactor: Update ShutdownCommand.java --- src/main/java/com/mycmd/commands/ShutdownCommand.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/mycmd/commands/ShutdownCommand.java b/src/main/java/com/mycmd/commands/ShutdownCommand.java index 3e00db4..fa8eb19 100644 --- a/src/main/java/com/mycmd/commands/ShutdownCommand.java +++ b/src/main/java/com/mycmd/commands/ShutdownCommand.java @@ -38,12 +38,11 @@ public void execute(String[] args, ShellContext context) throws IOException { System.out.println("WARNING: This will execute a real shutdown command!"); System.out.print("Are you sure you want to continue? (yes/no): "); - try (java.util.Scanner scanner = new java.util.Scanner(System.in)) { - String confirmation = scanner.nextLine().trim().toLowerCase(); - if (!confirmation.equals("yes")) { - System.out.println("Shutdown cancelled."); - return; - } + java.util.Scanner scanner = new java.util.Scanner(System.in); + String confirmation = scanner.nextLine().trim().toLowerCase(); + if (!confirmation.equals("yes")) { + System.out.println("Shutdown cancelled."); + return; } try { From 6ce917923a6a727759348c85d36500d7d906fe2d Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:34:20 +0100 Subject: [PATCH 32/42] Refactor: Update ShellContext.java --- src/main/java/com/mycmd/ShellContext.java | 195 +++++++++++++++++++--- 1 file changed, 169 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index d833b00..ee17d13 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -1,41 +1,184 @@ package com.mycmd; import java.io.File; -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; +import java.util.*; +/** + * Context object that holds the shell's state including current directory, + * environment variables, command history, aliases, and shared Scanner. + */ public class ShellContext { + private File currentDir; + private final Map environment; + private final List history; + private final Map aliases; + private Scanner scanner; + private long startTime; - private File currentDir; - private final Map aliases; + public ShellContext() { + this.currentDir = new File(System.getProperty("user.dir")); + this.environment = new HashMap<>(); + this.history = new ArrayList<>(); + this.aliases = new HashMap<>(); + this.scanner = null; + this.startTime = System.currentTimeMillis(); + } + + // ==================== Scanner Management ==================== + + /** + * Set the shared Scanner instance for all commands to use. + * Should only be called once by App.java during initialization. + */ + public void setScanner(Scanner scanner) { + this.scanner = scanner; + } + + /** + * Get the shared Scanner instance. + * All commands should use this instead of creating their own Scanner. + * @return the shared Scanner instance + * @throws IllegalStateException if Scanner hasn't been initialized + */ + public Scanner getScanner() { + if (scanner == null) { + throw new IllegalStateException("Scanner not initialized in ShellContext"); + } + return scanner; + } + + // ==================== Directory Management ==================== + + public File getCurrentDir() { + return currentDir; + } + + public void setCurrentDir(File dir) { + if (dir != null && dir.exists() && dir.isDirectory()) { + this.currentDir = dir; + } + } + + /** + * Resolve a path relative to the current directory. + * If the path is absolute, return it as-is. + * If relative, resolve it against the current directory. + */ + public File resolvePath(String path) { + File file = new File(path); + if (file.isAbsolute()) { + return file; + } + return new File(currentDir, path); + } + + // ==================== Environment Variables ==================== + + public String getEnvVar(String key) { + return environment.get(key); + } + + public void setEnvVar(String key, String value) { + environment.put(key, value); + } - private Scanner scanner; + public Map getAllEnvVars() { + return new HashMap<>(environment); + } - public ShellContext() { - this.currentDir = new File(System.getProperty("user.dir")); - this.aliases = new HashMap<>(); - } + /** + * Legacy method name support for compatibility. + */ + public Map getEnvVars() { + return getAllEnvVars(); + } - public File getCurrentDir() { - return currentDir; - } + // ==================== Command History ==================== + + public void addToHistory(String command) { + history.add(command); + } - public void setCurrentDir(File dir) { - if (dir != null && dir.exists() && dir.isDirectory()) { - this.currentDir = dir; + public List getHistory() { + return new ArrayList<>(history); } - } - public Map getAliases() { - return aliases; - } + /** + * Legacy method name support for compatibility. + */ + public List getCommandHistory() { + return getHistory(); + } - public void addAlias(String name, String command) { - aliases.put(name, command); - } + public void clearHistory() { + history.clear(); + } - public String resolveAlias(String cmd) { - return aliases.getOrDefault(cmd, cmd); - } + // ==================== Aliases ==================== + + /** + * Get all aliases (for compatibility with existing code). + */ + public Map getAliases() { + return new HashMap<>(aliases); + } + + /** + * Add an alias (for compatibility with existing code). + */ + public void addAlias(String name, String command) { + aliases.put(name, command); + } + + /** + * Resolve an alias (for compatibility with existing code). + */ + public String resolveAlias(String cmd) { + return aliases.getOrDefault(cmd, cmd); + } + + /** + * Set an alias. + */ + public void setAlias(String alias, String command) { + aliases.put(alias, command); + } + + /** + * Get alias command. + */ + public String getAlias(String alias) { + return aliases.get(alias); + } + + /** + * Check if alias exists. + */ + public boolean hasAlias(String alias) { + return aliases.containsKey(alias); + } + + /** + * Remove an alias. + */ + public void removeAlias(String alias) { + aliases.remove(alias); + } + + /** + * Get all aliases. + */ + public Map getAllAliases() { + return new HashMap<>(aliases); + } + + // ==================== Start Time (for uptime command) ==================== + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } } From 7eeb4905c6783e34e02218693e2fa541fa4e08bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 13:34:38 +0000 Subject: [PATCH 33/42] Apply Spotless formatting --- src/main/java/com/mycmd/ShellContext.java | 328 ++++++++++------------ 1 file changed, 154 insertions(+), 174 deletions(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index ee17d13..2361156 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -4,181 +4,161 @@ import java.util.*; /** - * Context object that holds the shell's state including current directory, - * environment variables, command history, aliases, and shared Scanner. + * Context object that holds the shell's state including current directory, environment variables, + * command history, aliases, and shared Scanner. */ public class ShellContext { - private File currentDir; - private final Map environment; - private final List history; - private final Map aliases; - private Scanner scanner; - private long startTime; - - public ShellContext() { - this.currentDir = new File(System.getProperty("user.dir")); - this.environment = new HashMap<>(); - this.history = new ArrayList<>(); - this.aliases = new HashMap<>(); - this.scanner = null; - this.startTime = System.currentTimeMillis(); - } - - // ==================== Scanner Management ==================== - - /** - * Set the shared Scanner instance for all commands to use. - * Should only be called once by App.java during initialization. - */ - public void setScanner(Scanner scanner) { - this.scanner = scanner; - } - - /** - * Get the shared Scanner instance. - * All commands should use this instead of creating their own Scanner. - * @return the shared Scanner instance - * @throws IllegalStateException if Scanner hasn't been initialized - */ - public Scanner getScanner() { - if (scanner == null) { - throw new IllegalStateException("Scanner not initialized in ShellContext"); - } - return scanner; - } - - // ==================== Directory Management ==================== - - public File getCurrentDir() { - return currentDir; - } - - public void setCurrentDir(File dir) { - if (dir != null && dir.exists() && dir.isDirectory()) { - this.currentDir = dir; - } - } - - /** - * Resolve a path relative to the current directory. - * If the path is absolute, return it as-is. - * If relative, resolve it against the current directory. - */ - public File resolvePath(String path) { - File file = new File(path); - if (file.isAbsolute()) { - return file; - } - return new File(currentDir, path); - } - - // ==================== Environment Variables ==================== - - public String getEnvVar(String key) { - return environment.get(key); - } - - public void setEnvVar(String key, String value) { - environment.put(key, value); - } - - public Map getAllEnvVars() { - return new HashMap<>(environment); - } - - /** - * Legacy method name support for compatibility. - */ - public Map getEnvVars() { - return getAllEnvVars(); - } - - // ==================== Command History ==================== - - public void addToHistory(String command) { - history.add(command); - } - - public List getHistory() { - return new ArrayList<>(history); - } + private File currentDir; + private final Map environment; + private final List history; + private final Map aliases; + private Scanner scanner; + private long startTime; + + public ShellContext() { + this.currentDir = new File(System.getProperty("user.dir")); + this.environment = new HashMap<>(); + this.history = new ArrayList<>(); + this.aliases = new HashMap<>(); + this.scanner = null; + this.startTime = System.currentTimeMillis(); + } + + // ==================== Scanner Management ==================== + + /** + * Set the shared Scanner instance for all commands to use. Should only be called once by App.java + * during initialization. + */ + public void setScanner(Scanner scanner) { + this.scanner = scanner; + } + + /** + * Get the shared Scanner instance. All commands should use this instead of creating their own + * Scanner. + * + * @return the shared Scanner instance + * @throws IllegalStateException if Scanner hasn't been initialized + */ + public Scanner getScanner() { + if (scanner == null) { + throw new IllegalStateException("Scanner not initialized in ShellContext"); + } + return scanner; + } + + // ==================== Directory Management ==================== + + public File getCurrentDir() { + return currentDir; + } + + public void setCurrentDir(File dir) { + if (dir != null && dir.exists() && dir.isDirectory()) { + this.currentDir = dir; + } + } + + /** + * Resolve a path relative to the current directory. If the path is absolute, return it as-is. If + * relative, resolve it against the current directory. + */ + public File resolvePath(String path) { + File file = new File(path); + if (file.isAbsolute()) { + return file; + } + return new File(currentDir, path); + } + + // ==================== Environment Variables ==================== + + public String getEnvVar(String key) { + return environment.get(key); + } + + public void setEnvVar(String key, String value) { + environment.put(key, value); + } + + public Map getAllEnvVars() { + return new HashMap<>(environment); + } + + /** Legacy method name support for compatibility. */ + public Map getEnvVars() { + return getAllEnvVars(); + } + + // ==================== Command History ==================== + + public void addToHistory(String command) { + history.add(command); + } + + public List getHistory() { + return new ArrayList<>(history); + } + + /** Legacy method name support for compatibility. */ + public List getCommandHistory() { + return getHistory(); + } + + public void clearHistory() { + history.clear(); + } + + // ==================== Aliases ==================== + + /** Get all aliases (for compatibility with existing code). */ + public Map getAliases() { + return new HashMap<>(aliases); + } + + /** Add an alias (for compatibility with existing code). */ + public void addAlias(String name, String command) { + aliases.put(name, command); + } + + /** Resolve an alias (for compatibility with existing code). */ + public String resolveAlias(String cmd) { + return aliases.getOrDefault(cmd, cmd); + } + + /** Set an alias. */ + public void setAlias(String alias, String command) { + aliases.put(alias, command); + } + + /** Get alias command. */ + public String getAlias(String alias) { + return aliases.get(alias); + } + + /** Check if alias exists. */ + public boolean hasAlias(String alias) { + return aliases.containsKey(alias); + } + + /** Remove an alias. */ + public void removeAlias(String alias) { + aliases.remove(alias); + } - /** - * Legacy method name support for compatibility. - */ - public List getCommandHistory() { - return getHistory(); - } - - public void clearHistory() { - history.clear(); - } - - // ==================== Aliases ==================== - - /** - * Get all aliases (for compatibility with existing code). - */ - public Map getAliases() { - return new HashMap<>(aliases); - } - - /** - * Add an alias (for compatibility with existing code). - */ - public void addAlias(String name, String command) { - aliases.put(name, command); - } - - /** - * Resolve an alias (for compatibility with existing code). - */ - public String resolveAlias(String cmd) { - return aliases.getOrDefault(cmd, cmd); - } - - /** - * Set an alias. - */ - public void setAlias(String alias, String command) { - aliases.put(alias, command); - } - - /** - * Get alias command. - */ - public String getAlias(String alias) { - return aliases.get(alias); - } - - /** - * Check if alias exists. - */ - public boolean hasAlias(String alias) { - return aliases.containsKey(alias); - } - - /** - * Remove an alias. - */ - public void removeAlias(String alias) { - aliases.remove(alias); - } - - /** - * Get all aliases. - */ - public Map getAllAliases() { - return new HashMap<>(aliases); - } - - // ==================== Start Time (for uptime command) ==================== - - public long getStartTime() { - return startTime; - } - - public void setStartTime(long startTime) { - this.startTime = startTime; - } + /** Get all aliases. */ + public Map getAllAliases() { + return new HashMap<>(aliases); + } + + // ==================== Start Time (for uptime command) ==================== + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } } From 5f246d29a8fa24a55eb9a17c277b327e6b57629c Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:36:07 +0100 Subject: [PATCH 34/42] Refactor: Update MoveCommand.java --- .../java/com/mycmd/commands/MoveCommand.java | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/mycmd/commands/MoveCommand.java b/src/main/java/com/mycmd/commands/MoveCommand.java index 0abc563..7fd0da2 100644 --- a/src/main/java/com/mycmd/commands/MoveCommand.java +++ b/src/main/java/com/mycmd/commands/MoveCommand.java @@ -19,26 +19,37 @@ * move operation. */ public class MoveCommand implements Command { - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Usage: " + usage()); - return; + + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Usage: " + usage()); + return; + } + + Path source = context.resolvePath(args[0]).toPath(); + Path destination = context.resolvePath(args[1]).toPath(); + + if (!Files.exists(source)) { + System.out.println("The system cannot find the file specified."); + return; + } + + try { + Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING); + System.out.println("Moved: " + source.getFileName() + " -> " + destination); + } catch (IOException e) { + System.out.println("Error moving file: " + e.getMessage()); + } } - - Path source = context.resolvePath(args[0]).toPath(); - Path destination = context.resolvePath(args[1]).toPath(); - - if (!Files.exists(source)) { - System.out.println("The system cannot find the file specified."); - return; + + @Override + public String description() { + return "Move or rename files and directories"; } - - try { - Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING); - System.out.println("Moved: " + source.getFileName() + " -> " + destination); - } catch (IOException e) { - System.out.println("Error moving file: " + e.getMessage()); + + @Override + public String usage() { + return "move "; } - } } From 87b65ef12d8c1b8bd7e2c9da6f596a206e3399f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 13:36:23 +0000 Subject: [PATCH 35/42] Apply Spotless formatting --- .../java/com/mycmd/commands/MoveCommand.java | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/mycmd/commands/MoveCommand.java b/src/main/java/com/mycmd/commands/MoveCommand.java index 7fd0da2..3ab207e 100644 --- a/src/main/java/com/mycmd/commands/MoveCommand.java +++ b/src/main/java/com/mycmd/commands/MoveCommand.java @@ -19,37 +19,37 @@ * move operation. */ public class MoveCommand implements Command { - - @Override - public void execute(String[] args, ShellContext context) throws IOException { - if (args.length < 2) { - System.out.println("Usage: " + usage()); - return; - } - - Path source = context.resolvePath(args[0]).toPath(); - Path destination = context.resolvePath(args[1]).toPath(); - - if (!Files.exists(source)) { - System.out.println("The system cannot find the file specified."); - return; - } - - try { - Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING); - System.out.println("Moved: " + source.getFileName() + " -> " + destination); - } catch (IOException e) { - System.out.println("Error moving file: " + e.getMessage()); - } + + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length < 2) { + System.out.println("Usage: " + usage()); + return; } - - @Override - public String description() { - return "Move or rename files and directories"; + + Path source = context.resolvePath(args[0]).toPath(); + Path destination = context.resolvePath(args[1]).toPath(); + + if (!Files.exists(source)) { + System.out.println("The system cannot find the file specified."); + return; } - - @Override - public String usage() { - return "move "; + + try { + Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING); + System.out.println("Moved: " + source.getFileName() + " -> " + destination); + } catch (IOException e) { + System.out.println("Error moving file: " + e.getMessage()); } + } + + @Override + public String description() { + return "Move or rename files and directories"; + } + + @Override + public String usage() { + return "move "; + } } From 5e02821f382e24d2d440ec094894e1f305fd0513 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:42:58 +0100 Subject: [PATCH 36/42] Refactor : Update ShellContext.java --- src/main/java/com/mycmd/ShellContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index 2361156..8a6ed6d 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -17,7 +17,7 @@ public class ShellContext { public ShellContext() { this.currentDir = new File(System.getProperty("user.dir")); - this.environment = new HashMap<>(); + this.environment = new HashMap<>()(System.getenv()); this.history = new ArrayList<>(); this.aliases = new HashMap<>(); this.scanner = null; From 14c8e843749175144b112586e8028f8e8d5a15fa Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:48:11 +0100 Subject: [PATCH 37/42] Refactor: Update formatter.yml --- .github/workflows/formatter.yml | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/.github/workflows/formatter.yml b/.github/workflows/formatter.yml index 955d0b6..b3f268d 100644 --- a/.github/workflows/formatter.yml +++ b/.github/workflows/formatter.yml @@ -1,25 +1,23 @@ -name: Apply Spotless Formatting +name: ๐Ÿงผ Apply Spotless Formatting on: - pull_request: - branches: - - main push: - branches: - - main + branches: [main] + +permissions: + contents: write jobs: format: runs-on: ubuntu-latest concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + group: ${{ github.workflow }}-${{ github.ref_name }} cancel-in-progress: true steps: - name: Checkout repository uses: actions/checkout@v4 with: - ref: ${{ github.head_ref || github.ref_name }} fetch-depth: 0 - name: Set up JDK 17 @@ -32,15 +30,15 @@ jobs: - name: Apply Spotless formatting run: mvn spotless:apply - - name: Commit changes if any + - name: Commit and push formatting changes run: | git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" - git add . - if ! git diff --quiet --staged; then + git add -A + if ! git diff --cached --quiet; then git commit -m "Apply Spotless formatting" - git pull --rebase origin ${{ github.head_ref || github.ref_name }} - git push origin HEAD:${{ github.head_ref || github.ref_name }} + git pull --rebase --autostash origin ${{ github.ref_name }} + git push origin HEAD:${{ github.ref_name }} else - echo "No formatting changes to commit." + echo "โœ… No formatting changes to commit." fi From 1c37f32bbc61c45044bf34b9a8f0266a48f7008b Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:54:33 +0100 Subject: [PATCH 38/42] Refactor: Update ShellContext.java --- src/main/java/com/mycmd/ShellContext.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index 8a6ed6d..5f54c1b 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -17,13 +17,14 @@ public class ShellContext { public ShellContext() { this.currentDir = new File(System.getProperty("user.dir")); - this.environment = new HashMap<>()(System.getenv()); + this.environment = new HashMap<>(System.getenv()); this.history = new ArrayList<>(); this.aliases = new HashMap<>(); this.scanner = null; this.startTime = System.currentTimeMillis(); } + // ==================== Scanner Management ==================== /** From 9d2f2bc1100df45c3e672ef5b15b381ec603fff5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Nov 2025 13:54:51 +0000 Subject: [PATCH 39/42] Apply Spotless formatting --- src/main/java/com/mycmd/ShellContext.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index 5f54c1b..8a96e55 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -24,7 +24,6 @@ public ShellContext() { this.startTime = System.currentTimeMillis(); } - // ==================== Scanner Management ==================== /** From 0824de1850abc77dfc2754d68cfe081d4c448d6e Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:07:14 +0100 Subject: [PATCH 40/42] Refactor: Update ShellContext.java Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/main/java/com/mycmd/ShellContext.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index 8a96e55..be6736a 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -55,9 +55,13 @@ public File getCurrentDir() { } public void setCurrentDir(File dir) { - if (dir != null && dir.exists() && dir.isDirectory()) { - this.currentDir = dir; + if (dir == null || !dir.exists()) { + throw new IllegalArgumentException("Directory does not exist: " + dir); } + if (!dir.isDirectory()) { + throw new IllegalArgumentException("Not a directory: " + dir); + } + this.currentDir = dir; } /** From 5971375e1840e4d322438820732051dd01b723eb Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:11:16 +0100 Subject: [PATCH 41/42] Refactor: Update formatter.yml --- .github/workflows/formatter.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/formatter.yml b/.github/workflows/formatter.yml index b3f268d..ddab8cf 100644 --- a/.github/workflows/formatter.yml +++ b/.github/workflows/formatter.yml @@ -37,7 +37,10 @@ jobs: git add -A if ! git diff --cached --quiet; then git commit -m "Apply Spotless formatting" - git pull --rebase --autostash origin ${{ github.ref_name }} + if ! git pull --rebase --autostash origin ${{ github.ref_name }}; then + echo "โŒ Rebase failed; manual intervention required." + exit 1 + fi git push origin HEAD:${{ github.ref_name }} else echo "โœ… No formatting changes to commit." From 98ccb2ef0e5b18c80ab0a7055c91fdeccb8d6ca5 Mon Sep 17 00:00:00 2001 From: Saurav Bhowmick <51038890+SauravBhowmick@users.noreply.github.com> Date: Tue, 11 Nov 2025 15:18:15 +0100 Subject: [PATCH 42/42] Refactor: Update ShellContext.java --- src/main/java/com/mycmd/ShellContext.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/mycmd/ShellContext.java b/src/main/java/com/mycmd/ShellContext.java index be6736a..75fb541 100644 --- a/src/main/java/com/mycmd/ShellContext.java +++ b/src/main/java/com/mycmd/ShellContext.java @@ -1,6 +1,7 @@ package com.mycmd; import java.io.File; +import java.time.Instant; import java.util.*; /** @@ -13,7 +14,7 @@ public class ShellContext { private final List history; private final Map aliases; private Scanner scanner; - private long startTime; + private Instant startTime; public ShellContext() { this.currentDir = new File(System.getProperty("user.dir")); @@ -21,7 +22,7 @@ public ShellContext() { this.history = new ArrayList<>(); this.aliases = new HashMap<>(); this.scanner = null; - this.startTime = System.currentTimeMillis(); + this.startTime = Instant.now(); } // ==================== Scanner Management ==================== @@ -158,11 +159,11 @@ public Map getAllAliases() { // ==================== Start Time (for uptime command) ==================== - public long getStartTime() { + public Instant getStartTime() { return startTime; } - public void setStartTime(long startTime) { + public void setStartTime(Instant startTime) { this.startTime = startTime; } }