paulo1205
(usa Ubuntu)
Enviado em 13/03/2016 - 15:29h
Você pode criar um atalho para o programa, e no atalho informar que o programa em questão precisa de um terminal. Quando o ambiente gráfico vir que está executando tal programa, vai chamar um terminal e executar o programa dentro dele.
Você pode embutir essa inteligência no próprio programa, também. Para tanto, você tenta abrir
/dev/tty . Se conseguir, então já tem um terminal associado. Se não, você pode reexecutar o programa dentro de um terminal.
Segue um exemplo (não testado, porém essencialmente correto ou muito próximo disso) de como, mais ou menos, fazer isso.
const char *terminal_search_order[]={
"konsole", // KDE
"gnome-terminal", // Gnome
"xterm", // X11 padrão
"rxvt", // X11 (suportamente mais leve)
NULL // Fim da lista.
};
int main(int argc, char **argv){
int tty_fd=open("/dev/tty", O_RDWR, 0644);
if(tty_fd!=-1){
// Já tem terminal associado. Não faz nada, a não ser fechar o
// descritor usado no teste.
close(tty_fd);
}
else{
// Não temos um terminal. Vamos tentar conseguir um.
if(getenv("DISPLAY")!=NULL){
// Existe (supostamente) um X11. Tenta reexecutar o programa
// dentro de algum dos possíveis terminais gráficos.
char **term_argv;
term_argv=malloc((argc+3)*sizeof *term_argv);
if(term_argv==NULL){
fprintf(stderr, "Falha ao alocar memória: %s.\n", strerror(errno));
exit(1);
}
term_argv[1]="-e"; // Em C++, “const_cast<char *>("-e")”.
for(int n=0; n<=argc; n++)
term_argv[n+2]=argv[n];
// Tenta os vários tipos de terminal.
const char **ppt;
for(ppt=terminal_search_order; *ppt!=NULL; ppt++){
term_argv[0]=(char *)*ppt; // Em C++, “const_cast<char *>(ppt)”.
execvp(term_argv[0], term_argv);
}
// Todos os terminais gráficos falharam. Deixa seguir pelo código
// abaixo, que tenta conseguir terminal de texto.
}
// Tenta conseguir um terminal de texto usando o “screen”.
/*
Se for um programa interativo (i.e. se pedir para ler dados do
terminal, o usuário terá de se conectar ao terminal), chamando
"screen -r", para poder interagir com o programa. Por outro
lado, se o programa não solicitar entrada de dados e terminar
de executar, a sessão do screen também vai terminar, e não
será mais possível ver a saída gerada (a não ser que você
defina um valor para a opção “zombie“ no arquivo de
configuração do screen).
*/
char **term_argv=malloc((argc+4)*sizeof *term_argv);
if(term_argv==NULL){
fprintf(stderr, "Falha ao alocar memória: %s.\n", strerror(errno));
exit(1);
}
term_argv[0]=(char *)"screen";
term_argv[1]=(char *)"-d";
term_argv[2]=(char *)"-m";
for(int n=0; n<=argc; n++)
term_argv[n+3]=argv[n];
execvp(term_argv[0], term_argv);
// Se chegou aqui, falhou a execução dentro do screen.
// Dependendo do programa, pode ser melhor abortar, mas
// eu aqui simplesmente deixo a execução seguir.
}
// Programa prossegue daqui.
// (...)
}