Com o código-fonte aberto, você pode ver o código e ver se pode ser fácil fazer o que quiser. No meu antigo Fedora baseado em rpm, eu poderia facilmente baixar e descompactar a fonte com
$ rpm -qf /usr/bin/top
procps-ng-3.3.10-11.fc24.x86_64
$ dnf download --source procps-ng
$ rpm -i procps-ng-3.3.10-11.fc24.src.rpm
$ rpmbuild -bp ~/rpmbuild/SPECS/procps-ng.spec --nodeps
$ cd ~/rpmbuild/BUILD/procps-ng-3.3.10/
e o código está em top/top.c
. Procurando a palavra filtro , eventualmente, mostra que a função other_selection()
está implementando o comando o
ou O
com uma estrutura C pequena na qual sel = strcasestr
ou sel = strstr
está sendo definido para entrada como como COMMAND=somestring
. Você pode ver o código gitlab desta versão. Ele mudou desde então, mas é semelhante.
Um meio de implementar um ou entre 2 strings parecia um pouco difícil, mas uma alternativa simples parece aceitar uma expressão regular em vez de apenas fazer uma comparação de strings. Você pode então alterar a atribuição para sel = myfunction
e escrever uma função que leve 2 strings e faça um regexec()
em vez de strstr()
.
Se você preferir não baixar e compilar o programa, você pode escrever um pequeno shim para carregar na frente da biblioteca C que substitui a função strstr()
por sua própria. No entanto, eu achei que essa função foi usada em outros lugares por top
, então eu preferi substituir strcasestr()
, que parece ser usado apenas para o comando o
. Crie um arquivo shim_strcasestr.c
com o seguinte:
/* capture calls to a routine and replace with your code
* https://unix.stackexchange.com/a/463461/119298
* gcc -Wall -O2 -fpic -shared -ldl -o shim_strcasestr.so shim_strcasestr.c */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <regex.h>
#define NUMMATCH 1 /* max num matching capture groups in pattern */
char *strcasestr(const char *haystack, const char *needle){
static char *(*real_strcasestr)(const char *haystack, const char *needle) = NULL;
regex_t myexpn;
regmatch_t matches[NUMMATCH] = {0};
if (!real_strcasestr) {
real_strcasestr = dlsym(RTLD_NEXT, "strcasestr");
char *error = dlerror();
if (error != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
}
if(needle[0]!='/') return real_strcasestr(haystack,needle);
int rc = regcomp(&myexpn, needle+1, REG_EXTENDED);
if(rc!=0)return NULL;
rc = regexec(&myexpn, haystack, NUMMATCH, matches, 0);
regfree(&myexpn);
if(rc==REG_NOMATCH)return NULL;
return (char*)haystack;
}
e compile como mostrado no comentário. Você pode, então, executá-lo como LD_PRELOAD=./shim_strcstr.so /usr/bin/top
e, quando digitar a chave o
, poderá inserir, por exemplo, COMMAND=/sshd|sleep
e obter o resultado desejado. Eu adicionei uma verificação para um /
inicial na string, então você ainda pode obter a correspondência original de qualquer caso, se você omiti-lo. Obviamente, esse código pode ser otimizado para armazenar em cache o resultado regcomp()
.