Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/java/com/mycmd/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ private static void registerCommands(Map<String, Command> 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());
Expand Down
172 changes: 152 additions & 20 deletions src/main/java/com/mycmd/commands/PingCommand.java
Original file line number Diff line number Diff line change
@@ -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 <hostname> : Ping the specified host with default count (4 packets)
* - ping <hostname> -t : Ping continuously until stopped (Windows-style)
* - ping <hostname> -n <count> : 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 <hostname>");
public class PingCommand implements Command {

@Override
public void execute(String[] args, ShellContext context) throws IOException {
if (args.length == 0) {
System.out.println("Usage: ping <hostname> [options]");
System.out.println("Options:");
System.out.println(" -t Ping continuously until stopped");
System.out.println(" -n <count> 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<String> 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<String> 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 <hostname> [options]";
}
}