diff --git a/Action.c b/Action.c index 1d3bccc51..702a899e6 100644 --- a/Action.c +++ b/Action.c @@ -519,18 +519,37 @@ static Htop_Reaction actionKill(State* st) { static int preSelectedSignal = SIGNALSPANEL_INITSELECTEDSIGNAL; + Process_sendSignalContext ctx; + Panel* signalsPanel = SignalsPanel_new(preSelectedSignal); const ListItem* sgn = (ListItem*) Action_pickFromVector(st, signalsPanel, 14, true); if (sgn && sgn->key != 0) { + ctx.sgn = sgn->key; + ctx.sawEperm = false; + ctx.lastRealErrno = 0; preSelectedSignal = sgn->key; Panel_setHeader((Panel*)st->mainPanel, "Sending..."); Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st)); refresh(); - bool ok = MainPanel_foreachRow(st->mainPanel, Process_rowSendSignal, (Arg) { .i = sgn->key }, NULL); - if (!ok) { + bool ok = MainPanel_foreachRow(st->mainPanel, Process_rowSendSignal, (Arg) { .v = &ctx }, NULL); + (void) ok; + if (ctx.sawEperm) { + beep(); + Panel_setHeader((Panel*)st->mainPanel, "Permission denied"); + Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st)); + refresh(); + napms(1500); + } + else if (ctx.lastRealErrno != 0) { beep(); + Panel_setHeader((Panel*)st->mainPanel, strerror(ctx.lastRealErrno)); + Panel_draw((Panel*)st->mainPanel, false, true, true, State_hideFunctionBar(st)); + refresh(); + napms(1500); + } + else { + napms(500); } - napms(500); } Panel_delete((Object*)signalsPanel); diff --git a/Process.c b/Process.c index cd1c08688..f5f83ab38 100644 --- a/Process.c +++ b/Process.c @@ -19,6 +19,7 @@ in the source distribution for its full text. #include #include #include +#include #include "CRT.h" #include "Hashtable.h" @@ -901,14 +902,25 @@ bool Process_rowChangePriorityBy(Row* super, Arg delta) { return Process_setPriority(this, (int)this->nice + delta.i); } -static bool Process_sendSignal(Process* this, Arg sgn) { - return kill(Process_getPid(this), sgn.i) == 0; +static bool Process_sendSignal(Process* this, Process_sendSignalContext* ctx) { + if (kill(Process_getPid(this), ctx->sgn ) != 0) { + int e = errno; + if (e == EPERM) { + ctx->sawEperm = true; + } + if (e != ESRCH) { + ctx->lastRealErrno = e; + } + return false; + } + return true; } -bool Process_rowSendSignal(Row* super, Arg sgn) { +bool Process_rowSendSignal(Row* super, Arg arg) { Process* this = (Process*) super; assert(Object_isA((const Object*) this, (const ObjectClass*) &Process_class)); - return Process_sendSignal(this, sgn); + Process_sendSignalContext* ctx = (Process_sendSignalContext*) arg.v; + return Process_sendSignal(this, ctx); } int Process_compare(const void* v1, const void* v2) { diff --git a/Process.h b/Process.h index 38e2711f6..3f4b83e55 100644 --- a/Process.h +++ b/Process.h @@ -309,6 +309,12 @@ const char* Process_rowGetSortKey(Row* super); bool Process_rowChangePriorityBy(Row* super, Arg delta); +typedef struct Process_sendSignalContext_ { + int sgn; + bool sawEperm; + int lastRealErrno; +} Process_sendSignalContext; + bool Process_rowSendSignal(Row* super, Arg sgn); bool Process_rowIsHighlighted(const Row* super);