diff --git a/src/Renci.SshNet/CommandSignals.cs b/src/Renci.SshNet/CommandSignals.cs new file mode 100644 index 000000000..ceb84d475 --- /dev/null +++ b/src/Renci.SshNet/CommandSignals.cs @@ -0,0 +1,73 @@ +namespace Renci.SshNet +{ + /// + /// The ssh compatible standard POSIX/ANSI signals. + /// + public static class CommandSignals + { + /// + /// Hangup (POSIX). + /// + public const string SIGHUP = "HUP"; + + /// + /// Interrupt (ANSI). + /// + public const string SIGINT = "INT"; + + /// + /// Quit (POSIX). + /// + public const string SIGQUIT = "QUIT"; + + /// + /// Illegal instruction (ANSI). + /// + public const string SIGILL = "ILL"; + + /// + /// Abort (ANSI). + /// + public const string SIGABRT = "ABRT"; + + /// + /// Floating-point exception (ANSI). + /// + public const string SIGFPE = "FPE"; + + /// + /// Kill, unblockable (POSIX). + /// + public const string SIGKILL = "KILL"; + + /// + /// User-defined signal 1 (POSIX). + /// + public const string SIGUSR1 = "USR1"; + + /// + /// Segmentation violation (ANSI). + /// + public const string SIGSEGV = "SEGV"; + + /// + /// User-defined signal 2 (POSIX). + /// + public const string SIGUSR2 = "USR2"; + + /// + /// Broken pipe (POSIX). + /// + public const string SIGPIPE = "PIPE"; + + /// + /// Alarm clock (POSIX). + /// + public const string SIGALRM = "ALRM"; + + /// + /// Termination (ANSI). + /// + public const string SIGTERM = "TERM"; + } +} diff --git a/src/Renci.SshNet/SshCommand.cs b/src/Renci.SshNet/SshCommand.cs index ce1042244..a66065d70 100644 --- a/src/Renci.SshNet/SshCommand.cs +++ b/src/Renci.SshNet/SshCommand.cs @@ -478,6 +478,61 @@ public void CancelAsync(bool forceKill = false, int millisecondsTimeout = 500) } } + /// + /// Tries to send a POSIX/ANSI signal to the remote process executing the command, such as SIGTERM or any of the . + /// + /// The signal to send. See for a standard list of signals. + /// If the signal was sent. + public bool TrySendSignal(string signal) + { + if (signal is null) + { + return false; + } + + if (_tcs is null || _tcs.Task.IsCompleted || _channel?.IsOpen != true) + { + return false; + } + + try + { + // Try to send the cancellation signal. + return _channel.SendSignalRequest(signal); + } + catch (Exception) + { + // Exception can be ignored since we are in a Try method + // Possible exceptions here: InvalidOperationException, SshConnectionException, SshOperationTimeoutException + } + + return false; + } + + /// + /// Tries to send a POSIX/ANSI signal to the remote process executing the command, such as SIGTERM or any of the . + /// + /// The signal to send. See for a standard list of signals. + /// Signal was not a valid CommandSignal. + /// The client is not connected. + /// The operation timed out. + /// The size of the packet exceeds the maximum size defined by the protocol. + /// Command has not been started. + public void SendSignal(string signal) + { + if (signal is null) + { + throw new ArgumentException("Signal was not a valid CommandSignal."); + } + + if (_tcs is null || _tcs.Task.IsCompleted || _channel?.IsOpen != true) + { + throw new InvalidOperationException("Command has not been started."); + } + + _ = _channel.SendSignalRequest(signal); + } + /// /// Executes the command specified by . ///