2021-02-18 22:25:36 +01:00
#include "fastfetch.h"
2021-04-28 19:53:30 +02:00
#include <string.h>
#include <unistd.h>
#include <pthread.h>
2021-04-15 18:59:26 +02:00
#define FF_TERMINAL_MODULE_NAME "Terminal"
#define FF_TERMINAL_NUM_FORMAT_ARGS 3
2021-05-01 16:54:59 +02:00
static inline void getTerminalFromEnv ( FFTerminalResult * result )
{
char * term = getenv ( "TERM" );
//TTY
if ( term == NULL || strcasecmp ( term , "linux" ) == 0 )
term = ttyname ( STDIN_FILENO );
ffStrbufSetS ( & result -> exeName , term );
ffStrbufSetS ( & result -> processName , term );
}
2021-04-28 19:53:30 +02:00
static void getTerminalName ( FFinstance * instance , const char * pid , FFTerminalResult * result )
{
char statFile [ 234 ];
sprintf ( statFile , "/proc/%s/stat" , pid );
FILE * stat = fopen ( statFile , "r" );
if ( stat == NULL )
{
ffStrbufSetF ( & result -> error , "fopen( \" %s \" , \" r \" ) == NULL" , statFile );
return ;
}
char name [ 256 ];
char ppid [ 256 ];
2021-05-13 12:27:44 +02:00
if ( fscanf ( stat , "%*s (%255[^)])%*s%255s" , name , ppid ) != 2 )
2021-04-28 19:53:30 +02:00
{
ffStrbufSetS ( & result -> error , "fscanf(stat, \" %*s (%[^)])%*s%s \" , name, ppid) != 2" );
2021-05-13 12:27:44 +02:00
fclose ( stat );
2021-04-28 19:53:30 +02:00
return ;
}
fclose ( stat );
if (
strcasecmp ( name , "bash" ) == 0 ||
strcasecmp ( name , "sh" ) == 0 ||
strcasecmp ( name , "zsh" ) == 0 ||
strcasecmp ( name , "ksh" ) == 0 ||
strcasecmp ( name , "fish" ) == 0 ||
strcasecmp ( name , "sudo" ) == 0 ||
strcasecmp ( name , "su" ) == 0 ||
strcasecmp ( name , "doas" ) == 0 ||
2021-05-23 19:40:34 +02:00
strcasecmp ( name , "strace" ) == 0 ||
strcasecmp ( name , "gdb" ) == 0
) {
2021-04-28 19:53:30 +02:00
getTerminalName ( instance , ppid , result );
return ;
}
char cmdlineFile [ 234 ];
sprintf ( cmdlineFile , "/proc/%s/cmdline" , pid );
ffGetFileContent ( cmdlineFile , & result -> exeName );
ffStrbufSubstrBeforeFirstC ( & result -> exeName , '\0' );
ffStrbufSubstrAfterLastC ( & result -> exeName , '/' );
ffStrbufSetS ( & result -> processName , name );
}
const FFTerminalResult * ffDetectTerminal ( FFinstance * instance )
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;
static FFTerminalResult result ;
static bool init = false ;
pthread_mutex_lock ( & mutex );
if ( init )
{
pthread_mutex_unlock ( & mutex );
return & result ;
}
init = true ;
ffStrbufInit ( & result . exeName );
ffStrbufInit ( & result . processName );
ffStrbufInit ( & result . error );
char ppid [ 256 ];
sprintf ( ppid , "%i" , getppid ());
getTerminalName ( instance , ppid , & result );
2021-05-01 16:54:59 +02:00
// This is mainly used when running in TTY. It also provides an fallback to $TERM if we _somehow_ failed
if (
ffStrbufStartsWithIgnCaseS ( & result . exeName , "login" ) ||
ffStrbufIgnCaseCompS ( & result . exeName , "systemd" ) == 0 ||
ffStrbufIgnCaseCompS ( & result . exeName , "init" ) == 0 ||
ffStrbufIgnCaseCompS ( & result . exeName , "(init)" ) == 0
) getTerminalFromEnv ( & result );
2021-04-28 19:53:30 +02:00
pthread_mutex_unlock ( & mutex );
return & result ;
}
2021-03-11 17:21:18 +01:00
void ffPrintTerminal ( FFinstance * instance )
{
2021-04-28 19:53:30 +02:00
const FFTerminalResult * result = ffDetectTerminal ( instance );
2021-03-19 20:57:07 +01:00
2021-04-22 21:41:42 +02:00
if ( result -> error . length > 0 )
2021-04-16 20:22:38 +02:00
{
2021-04-22 21:41:42 +02:00
ffPrintError ( instance , FF_TERMINAL_MODULE_NAME , 0 , & instance -> config . terminalKey , & instance -> config . terminalFormat , FF_TERMINAL_NUM_FORMAT_ARGS , result -> error . chars );
2021-04-16 20:22:38 +02:00
return ;
}
2021-04-02 16:21:52 +02:00
2021-04-22 21:41:42 +02:00
if ( result -> exeName . length == 0 && result -> processName . length == 0 )
2021-04-03 21:51:50 +02:00
{
2021-04-16 20:22:38 +02:00
ffPrintError ( instance , FF_TERMINAL_MODULE_NAME , 0 , & instance -> config . terminalKey , & instance -> config . terminalFormat , FF_TERMINAL_NUM_FORMAT_ARGS , "Terminal names not set" );
2021-04-03 21:51:50 +02:00
return ;
}
2021-04-22 21:41:42 +02:00
const FFstrbuf * name ;
2021-04-02 16:21:52 +02:00
2021-04-22 21:41:42 +02:00
if ( ffStrbufStartsWith ( & result -> exeName , & result -> processName ))
name = & result -> exeName ;
2021-04-02 16:21:52 +02:00
else
2021-04-22 21:41:42 +02:00
name = & result -> processName ;
2021-03-27 18:14:19 +01:00
2021-03-23 19:48:52 +01:00
if ( instance -> config . terminalFormat . length == 0 )
2021-03-11 17:21:18 +01:00
{
2021-04-15 18:59:26 +02:00
ffPrintLogoAndKey ( instance , FF_TERMINAL_MODULE_NAME , 0 , & instance -> config . terminalKey );
2021-04-02 16:21:52 +02:00
ffStrbufPutTo ( name , stdout );
2021-03-11 17:21:18 +01:00
}
else
{
2021-04-15 18:59:26 +02:00
ffPrintFormatString ( instance , FF_TERMINAL_MODULE_NAME , 0 , & instance -> config . terminalKey , & instance -> config . terminalFormat , NULL , FF_TERMINAL_NUM_FORMAT_ARGS , ( FFformatarg []){
2021-04-22 21:41:42 +02:00
{ FF_FORMAT_ARG_TYPE_STRBUF , & result -> exeName },
{ FF_FORMAT_ARG_TYPE_STRBUF , & result -> processName },
2021-04-15 18:59:26 +02:00
{ FF_FORMAT_ARG_TYPE_STRBUF , name }
});
2021-03-11 17:21:18 +01:00
}
2021-02-18 22:25:36 +01:00
}