diff --git a/src/main/java/com/mycmd/App.java b/src/main/java/com/mycmd/App.java index b79d37b..353acc3 100644 --- a/src/main/java/com/mycmd/App.java +++ b/src/main/java/com/mycmd/App.java @@ -77,6 +77,7 @@ private static void registerCommands(Map commands) { commands.put("tree", new TreeCommand()); commands.put("date", new DateCommand()); commands.put("history", new HistoryCommand()); + commands.put("ping", new PingCommand()); commands.put("pwd", new PwdCommand()); commands.put("uptime", new UptimeCommand()); commands.put("clearhistory", new ClearHistoryCommand()); diff --git a/src/main/java/com/mycmd/commands/PingCommand.java b/src/main/java/com/mycmd/commands/PingCommand.java index 92cffd1..e1d4a0b 100644 --- a/src/main/java/com/mycmd/commands/PingCommand.java +++ b/src/main/java/com/mycmd/commands/PingCommand.java @@ -1,49 +1,181 @@ +package com.mycmd.commands; + +import com.mycmd.Command; +import com.mycmd.ShellContext; + import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStreamReader; /** - * Executes the system ping command to test network connectivity. + * Tests network connectivity to a given hostname or IP address. + * + * This command wraps the system ping utility to send ICMP echo requests + * and displays response times or timeout status for each attempt. It uses + * the native ping command available on the operating system. * - * This is a standalone utility that wraps the Windows cmd.exe ping command. - * It executes the ping command as a subprocess and displays the output to - * the user, including network round-trip times and packet statistics. + * Usage: + * - ping : Ping the specified host with default count (4 packets) + * - ping -t : Ping continuously until stopped (Windows-style) + * - ping -n : Ping with specified packet count (Windows-style) * - * Usage: java PingCommand hostname + * Examples: + * - ping google.com + * - ping 8.8.8.8 + * - ping google.com -n 10 * - * Note: This implementation is Windows-specific as it uses "cmd.exe /c ping". - * The command requires at least one argument (the hostname or IP address to ping). - * It waits for the ping process to complete and displays the exit code. + * Note: This implementation uses the system's native ping command for + * accurate network connectivity testing and proper ICMP handling. */ -public class PingCommand { - public static void main(String[] args) { - if (args.length < 1) { - System.out.println("Usage: java PingCommand "); +public class PingCommand implements Command { + + @Override + public void execute(String[] args, ShellContext context) throws IOException { + if (args.length == 0) { + System.out.println("Usage: ping [options]"); + System.out.println("Options:"); + System.out.println(" -t Ping continuously until stopped"); + System.out.println(" -n Number of echo requests to send"); + System.out.println(); + System.out.println("Examples:"); + System.out.println(" ping google.com"); + System.out.println(" ping 8.8.8.8"); + System.out.println(" ping google.com -n 10"); return; } String host = args[0]; + + // Build ping command based on operating system + String[] command = buildPingCommand(host, args); try { - // Run the ping command - Process process = Runtime.getRuntime().exec("cmd.exe /c ping " + host); + // Execute the ping command + ProcessBuilder pb = new ProcessBuilder(command); + Process process = pb.start(); - // Read the output of the ping command + // Read and display output in real-time BufferedReader reader = new BufferedReader( new InputStreamReader(process.getInputStream()) ); + BufferedReader errorReader = new BufferedReader( + new InputStreamReader(process.getErrorStream()) + ); String line; + // Display standard output while ((line = reader.readLine()) != null) { System.out.println(line); } + + // Display error output if any + while ((line = errorReader.readLine()) != null) { + System.err.println(line); + } - // Wait for the process to finish + // Wait for the process to complete int exitCode = process.waitFor(); - System.out.println("Ping command exited with code: " + exitCode); + + if (exitCode != 0) { + System.out.println("Ping command failed with exit code: " + exitCode); + } - } catch (Exception e) { - System.out.println("Error executing ping command."); - e.printStackTrace(); + } catch (InterruptedException e) { + System.out.println("Ping command was interrupted."); + Thread.currentThread().interrupt(); + } catch (IOException e) { + throw new IOException("Failed to execute ping command: " + e.getMessage(), e); } } + + /** + * 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); + } + } + + /** + * Builds ping command for Windows systems. + */ + private String[] buildWindowsPingCommand(String host, String[] args) { + java.util.List command = new java.util.ArrayList<>(); + command.add("ping"); + + // Parse arguments for Windows ping options + boolean continuous = false; + int count = 4; // Default count + + for (int i = 1; i < args.length; i++) { + if ("-t".equals(args[i])) { + continuous = true; + } else if ("-n".equals(args[i]) && i + 1 < args.length) { + try { + count = Integer.parseInt(args[i + 1]); + i++; // Skip the next argument as it's the count value + } catch (NumberFormatException e) { + System.out.println("Warning: Invalid count value, using default (4)"); + } + } + } + + if (continuous) { + command.add("-t"); + } else { + command.add("-n"); + command.add(String.valueOf(count)); + } + + 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) { + java.util.List command = new java.util.ArrayList<>(); + command.add("ping"); + + // Parse arguments for Unix ping options + int count = 4; // Default count + + for (int i = 1; i < args.length; i++) { + if ("-t".equals(args[i])) { + // Unix ping doesn't use -t, just omit count for continuous + count = -1; + } else if ("-n".equals(args[i]) && i + 1 < args.length) { + try { + count = Integer.parseInt(args[i + 1]); + i++; // Skip the next argument as it's the count value + } catch (NumberFormatException e) { + System.out.println("Warning: Invalid count value, using default (4)"); + } + } + } + + if (count > 0) { + command.add("-c"); + command.add(String.valueOf(count)); + } + + 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 [options]"; + } }