From ebb14afb26a268963a84713dd685c64534a54c7c Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Thu, 18 Feb 2021 22:25:36 +0100 Subject: [PATCH] initial work --- .gitignore | 2 + CMakeLists.txt | 37 +++++++++ run.sh | 5 ++ src/battery.c | 31 ++++++++ src/break.c | 7 ++ src/colors.c | 20 +++++ src/cpu.c | 22 ++++++ src/desktopenvironment.c | 56 +++++++++++++ src/disk.c | 24 ++++++ src/fastfetch.c | 166 +++++++++++++++++++++++++++++++++++++++ src/fastfetch.h | 74 +++++++++++++++++ src/font.c | 46 +++++++++++ src/gpu.c | 50 ++++++++++++ src/host.c | 13 +++ src/icons.c | 24 ++++++ src/kernel.c | 7 ++ src/locale.c | 10 +++ src/logo.c | 98 +++++++++++++++++++++++ src/memory.c | 36 +++++++++ src/os.c | 24 ++++++ src/packages.c | 40 ++++++++++ src/resolution.c | 13 +++ src/seperator.c | 10 +++ src/shell.c | 17 ++++ src/terminal.c | 56 +++++++++++++ src/theme.c | 24 ++++++ src/title.c | 17 ++++ src/uptime.c | 19 +++++ 28 files changed, 948 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100755 run.sh create mode 100644 src/battery.c create mode 100644 src/break.c create mode 100644 src/colors.c create mode 100644 src/cpu.c create mode 100644 src/desktopenvironment.c create mode 100644 src/disk.c create mode 100644 src/fastfetch.c create mode 100644 src/fastfetch.h create mode 100644 src/font.c create mode 100644 src/gpu.c create mode 100644 src/host.c create mode 100644 src/icons.c create mode 100644 src/kernel.c create mode 100644 src/locale.c create mode 100644 src/logo.c create mode 100644 src/memory.c create mode 100644 src/os.c create mode 100644 src/packages.c create mode 100644 src/resolution.c create mode 100644 src/seperator.c create mode 100644 src/shell.c create mode 100644 src/terminal.c create mode 100644 src/theme.c create mode 100644 src/title.c create mode 100644 src/uptime.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..adb4006f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/build/ +**/.vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..fc7707313 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.0) + +project(fastfetch) + +include (${CMAKE_ROOT}/Modules/FindX11.cmake) + +add_executable(fastfetch + src/fastfetch.c + src/break.c + src/logo.c + src/title.c + src/seperator.c + src/os.c + src/host.c + src/kernel.c + src/uptime.c + src/packages.c + src/shell.c + src/resolution.c + src/desktopenvironment.c + src/theme.c + src/icons.c + src/font.c + src/terminal.c + src/cpu.c + src/gpu.c + src/memory.c + src/disk.c + src/battery.c + src/locale.c + src/colors.c +) + +target_link_libraries(fastfetch + ${X11_LIBRARIES} + pci +) \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100755 index 000000000..5ed1e161d --- /dev/null +++ b/run.sh @@ -0,0 +1,5 @@ +mkdir -p build/ +cd build/ +cmake .. +cmake --build . +./fastfetch diff --git a/src/battery.c b/src/battery.c new file mode 100644 index 000000000..78b548ddc --- /dev/null +++ b/src/battery.c @@ -0,0 +1,31 @@ +#include "fastfetch.h" + +void ffPrintBattery(FFstate* state) +{ + + FILE* fullFile = fopen("/sys/class/power_supply/BAT0/charge_full", "r"); + if(fullFile == NULL) + return; + uint32_t full; + fscanf(fullFile, "%lu", &full); + fclose(fullFile); + + FILE* nowFile = fopen("/sys/class/power_supply/BAT0/charge_full", "r"); + if(nowFile == NULL) + return; + uint32_t now; + fscanf(nowFile, "%lu", &now); + fclose(nowFile); + + FILE* statusFile = fopen("/sys/class/power_supply/BAT0/status", "r"); + if(statusFile == NULL) + return; + char status[256]; + fscanf(statusFile, "%s", status); + fclose(statusFile); + + uint32_t percentage = (now / (double) full) * 100; + + ffPrintLogoAndKey(state, "Battery"); + printf("%lu%% [%s]\n", percentage, status); +} \ No newline at end of file diff --git a/src/break.c b/src/break.c new file mode 100644 index 000000000..733fdaf85 --- /dev/null +++ b/src/break.c @@ -0,0 +1,7 @@ +#include "fastfetch.h" + +void ffPrintBreak(FFstate* state) +{ + ffPrintLogoLine(state); + putchar('\n'); +} \ No newline at end of file diff --git a/src/colors.c b/src/colors.c new file mode 100644 index 000000000..89494666e --- /dev/null +++ b/src/colors.c @@ -0,0 +1,20 @@ +#include "fastfetch.h" + +void ffPrintColors(FFstate* state) +{ + ffPrintLogoLine(state); + + for(uint8_t i = 0; i < 8; i++) + printf("\033[4%dm ", i); + + puts("\033[0m"); + + ffPrintLogoLine(state); + + for(uint8_t i = 8; i < 16; i++) + printf("\033[48;5;%dm ", i); + + puts("\033[0m"); + + puts(""); +} \ No newline at end of file diff --git a/src/cpu.c b/src/cpu.c new file mode 100644 index 000000000..07439bcb3 --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,22 @@ +#include "fastfetch.h" + +#include + +void ffPrintCPU(FFstate* state) +{ + char name[256]; + ffParsePropFile("/proc/cpuinfo", "model name%*s %[^\n]", name); + + char frequency[256]; + ffReadFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", frequency, 256); + + char cores[256]; + + uint32_t hz; + sscanf(frequency, "%ul", &hz); //in KHz + hz /= 1000; //to MHz + double ghz = (double) hz / 1000.0; //to GHz + + ffPrintLogoAndKey(state, "CPU"); + printf("%s (%i) @ %.9gGHz\n", name, get_nprocs(), ghz); +} \ No newline at end of file diff --git a/src/desktopenvironment.c b/src/desktopenvironment.c new file mode 100644 index 000000000..9c90efd68 --- /dev/null +++ b/src/desktopenvironment.c @@ -0,0 +1,56 @@ +#include "fastfetch.h" + +#include +#include + +static void printKDE() +{ + char* line = NULL; + char version[256]; + size_t len; + + FILE* plasma = fopen("/usr/share/xsessions/plasma.desktop", "r"); + if(plasma == NULL) + { + fputs("Error opening file: /usr/share/xsessions/plasma.desktop\n", stderr); + exit(35); + } + + while (getline(&line, &len, plasma) != -1) + { + if (sscanf(line, "X-KDE-PluginInfo-Version=%[^\n]", version) > 0) + break; + } + + fclose(plasma); + free(line); + printf("KDE Plasma %s", version); +} + +void ffPrintDesktopEnvironment(FFstate* state) +{ + const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP"); + if(currentDesktop == NULL) + return; + + ffPrintLogoAndKey(state, "DE"); + + if(strcmp(currentDesktop, "KDE") == 0) + printKDE(); + else + printf("%s", currentDesktop); + + const char* sessionType = getenv("XDG_SESSION_TYPE"); + if(sessionType == NULL) + putchar('\n'); + else if(strcmp(sessionType, "wayland") == 0) + puts(" (Wayland)"); + else if(strcmp(sessionType, "x11") == 0) + puts(" (X11)"); + else if(strcmp(sessionType, "tty") == 0) + puts(" TTY"); + else if(strcmp(sessionType, "mir") == 0) + puts(" (Mir)"); + else + printf(" (%s)\n", sessionType); +} \ No newline at end of file diff --git a/src/disk.c b/src/disk.c new file mode 100644 index 000000000..aa63592a5 --- /dev/null +++ b/src/disk.c @@ -0,0 +1,24 @@ +#include "fastfetch.h" + +#include + +void ffPrintDisk(FFstate* state) +{ + struct statvfs fs; + int ret = statvfs("/", &fs); + if(ret != 0) + { + return; + } + + const uint32_t GB = (1024 * 1024) * 1024; + + const uint32_t total = (fs.f_blocks * fs.f_frsize) / GB; + const uint32_t available = (fs.f_bfree * fs.f_frsize) / GB; + const uint32_t used = total - available; + const uint32_t percentage = (used / (double) total) * 100.0; + + + ffPrintLogoAndKey(state, "Disk (/)"); + printf("%luGB / %luGB (%lu%%)\n", used, total, percentage); +} \ No newline at end of file diff --git a/src/fastfetch.c b/src/fastfetch.c new file mode 100644 index 000000000..98c3d0a15 --- /dev/null +++ b/src/fastfetch.c @@ -0,0 +1,166 @@ +#include "fastfetch.h" + +#include + +void ffPrintKey(FFstate* state, const char* key) +{ + printf("%s"FASTFETCH_TEXT_MODIFIER_BOLT"%s"FASTFETCH_TEXT_MODIFIER_RESET": ", state->color, key); +} + +void ffPrintLogoAndKey(FFstate* state, const char* key) +{ + ffPrintLogoLine(state); + ffPrintKey(state, key); +} + +uint32_t ffTruncateLastNewline(char* buffer, uint32_t read) +{ + if(read == 0) + return read; + + if(buffer[read - 1] == '\n') + { + buffer[read - 1] = '\0'; + --read; + } + + return read; +} + +uint32_t ffReadFile(const char* fileName, char* buffer, uint32_t bufferSize) +{ + FILE* file = fopen(fileName, "r"); + if(file == NULL) + { + fprintf(stderr, "Failed to open file: %s\n", fileName); + exit(3); + } + + uint32_t read = fread(buffer, sizeof(char), bufferSize, file); + read = ffTruncateLastNewline(buffer, read); + + fclose(file); + + return read; +} + +void ffParsePropFile(const char* fileName, const char* regex, char* buffer) +{ + char* line = NULL; + size_t len; + + FILE* file = fopen(fileName, "r"); + if(file == NULL) + { + buffer[0] = '\0'; + return; + } + + while (getline(&line, &len, file) != -1) + { + if (sscanf(line, regex, buffer) > 0) + break; + } + + fclose(file); + free(line); +} + +void ffParsePropFileHome(FFstate* state, const char* relativeFile, const char* regex, char* buffer) +{ + char absolutePath[512]; + strcpy(absolutePath, state->passwd->pw_dir); + strcat(absolutePath, "/"); + strcat(absolutePath, relativeFile); + + ffParsePropFile(absolutePath, regex, buffer); +} + +static inline bool strSet(const char* str) +{ + return str != NULL && str[0] != '\0'; +} + +void ffPrintGtkPretty(const char* gtk2, const char* gtk3, const char* gtk4) +{ + if(strSet(gtk2) && strSet(gtk3) && strSet(gtk4)) + { + if((strcmp(gtk2, gtk3) == 0) && (strcmp(gtk2, gtk4) == 0)) + printf("%s [GTK2/3/4]", gtk2); + else if(strcmp(gtk2, gtk3) == 0) + printf("%s [GTK2/3], %s [GTK4]", gtk2, gtk4); + else if(strcmp(gtk3, gtk4) == 0) + printf("%s [GTK2], %s [GTK3/4]", gtk2, gtk3); + else + printf("%s [GTK2], %s [GTK3], %s [GTK4]", gtk2, gtk3, gtk4); + } + else if(strSet(gtk2) && strSet(gtk3)) + { + if(strcmp(gtk2, gtk3) == 0) + printf("%s [GTK2/3]", gtk2); + else + printf("%s [GTK2], %s [GTK3]", gtk2, gtk3); + } + else if(strSet(gtk3) && strSet(gtk4)) + { + if(strcmp(gtk3, gtk4) == 0) + printf("%s [GTK3/4]", gtk3); + else + printf("%s [GTK3], %s [GTK4]", gtk3, gtk4); + } + else if(strSet(gtk2)) + { + printf("%s [GTK2]", gtk2); + } + else if(strSet(gtk3)) + { + printf("%s [GTK3]", gtk3); + } + else if(strSet(gtk4)) + { + printf("%s [GTK4]", gtk4); + } +} + +int main(int argc, char** argv) +{ + FFstate state; + + //init + ffLoadLogo(&state); //Use ffLoadLogoSet to specify an image. Note that this also overwrites color + state.current_row = 0; + state.passwd = getpwuid(getuid()); + uname(&state.utsname); + sysinfo(&state.sysinfo); + + + //Configuration + state.logo_seperator = 4; + state.titleLength = 20; // This is overwritten by ffPrintTitle + + //Start the printing + ffPrintTitle(&state); + ffPrintSeperator(&state); + ffPrintOS(&state); + ffPrintHost(&state); + ffPrintKernel(&state); + ffPrintUptime(&state); + ffPrintPackages(&state); + ffPrintShell(&state); + ffPrintResolution(&state); + ffPrintDesktopEnvironment(&state); + ffPrintTheme(&state); + ffPrintIcons(&state); + ffPrintFont(&state); + ffPrintTerminal(&state); + ffPrintCPU(&state); + ffPrintGPU(&state); + ffPrintMemory(&state); + ffPrintDisk(&state); + ffPrintBattery(&state); + ffPrintLocale(&state); + ffPrintBreak(&state); + ffPrintColors(&state); + + return 0; +} diff --git a/src/fastfetch.h b/src/fastfetch.h new file mode 100644 index 000000000..b905929b7 --- /dev/null +++ b/src/fastfetch.h @@ -0,0 +1,74 @@ +#pragma once + +#ifndef FASTFETCH_INCLUDED +#define FASTFETCH_INCLUDED + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define FASTFETCH_TEXT_MODIFIER_BOLT "\033[1m" +#define FASTFETCH_TEXT_MODIFIER_RESET "\033[0m" + +typedef struct FFstate +{ + uint8_t current_row; + + uint8_t logo_width; + uint8_t logo_height; + char logo_chars[256][256]; + + uint8_t logo_seperator; + char color[10]; + + uint8_t titleLength; + struct passwd* passwd; + struct utsname utsname; + struct sysinfo sysinfo; +} FFstate; + +//Helper functions +void ffPrintLogoLine(FFstate* state); +void ffPrintKey(FFstate* state, const char* key); +void ffPrintLogoAndKey(FFstate* state, const char* key); +uint32_t ffTruncateLastNewline(char* buffer, uint32_t bufferSize); +uint32_t ffReadFile(const char* fileName, char* buffer, uint32_t bufferSize); +void ffParsePropFile(const char* file, const char* regex, char* buffer); +void ffParsePropFileHome(FFstate* state, const char* relativeFile, const char* regex, char* buffer); +void ffPrintGtkPretty(const char* gtk2, const char* gtk3, const char* gtk4); + +void ffLoadLogoSet(FFstate* state, const char* logo); +void ffLoadLogo(FFstate* state); + +void ffPrintBreak(FFstate* state); +void ffPrintTitle(FFstate* state); +void ffPrintSeperator(FFstate* state); +void ffPrintOS(FFstate* state); +void ffPrintHost(FFstate* state); +void ffPrintKernel(FFstate* state); +void ffPrintUptime(FFstate* state); +void ffPrintPackages(FFstate* state); +void ffPrintShell(FFstate* state); +void ffPrintResolution(FFstate* state); +void ffPrintDesktopEnvironment(FFstate* state); +void ffPrintTheme(FFstate* state); +void ffPrintIcons(FFstate* state); +void ffPrintFont(FFstate* state); +void ffPrintTerminal(FFstate* state); +void ffPrintCPU(FFstate* state); +void ffPrintGPU(FFstate* state); +void ffPrintMemory(FFstate* state); +void ffPrintDisk(FFstate* state); +void ffPrintBattery(FFstate* state); +void ffPrintLocale(FFstate* state); +void ffPrintColors(FFstate* state); + +#endif \ No newline at end of file diff --git a/src/font.c b/src/font.c new file mode 100644 index 000000000..27deda393 --- /dev/null +++ b/src/font.c @@ -0,0 +1,46 @@ +#include "fastfetch.h" + +static void parseFont(char* font, char* buffer) +{ + char name[64]; + char size[32]; + sscanf(font, "%[^,], %[^,]", name, size); + sprintf(buffer, "%s (%spt)", name, size); +} + +void ffPrintFont(FFstate* state) +{ + char plasma[256]; + ffParsePropFileHome(state, ".config/kdeglobals", "font=%[^\n]", plasma); + + char gtk2[256]; + ffParsePropFileHome(state, ".gtkrc-2.0", "gtk-font-name=\"%[^\"]+", gtk2); + char gtk2Pretty[256]; + parseFont(gtk2, gtk2Pretty); + + char gtk3[256]; + ffParsePropFileHome(state, ".config/gtk-3.0/settings.ini", "gtk-font-name=%[^\n]", gtk3); + char gtk3Pretty[256]; + parseFont(gtk3, gtk3Pretty); + + char gtk4[256]; + ffParsePropFileHome(state, ".config/gtk-4.0/settings.ini", "gtk-font-name=%[^\n]", gtk4); + char gtk4Pretty[256]; + parseFont(gtk4, gtk4Pretty); + + ffPrintLogoAndKey(state, "Font"); + + if(plasma[0] == '\0') + { + printf("Noto Sans (10pt) [Plasma], "); + } + else + { + char plasmaPretty[256]; + parseFont(plasma, plasmaPretty); + printf("%s [Plasma], ", plasmaPretty); + } + + ffPrintGtkPretty(gtk2Pretty, gtk3Pretty, gtk4Pretty); + putchar('\n'); +} \ No newline at end of file diff --git a/src/gpu.c b/src/gpu.c new file mode 100644 index 000000000..12d2bc656 --- /dev/null +++ b/src/gpu.c @@ -0,0 +1,50 @@ +#include "fastfetch.h" + +#include +#include + +static void handleGPU(FFstate* state, struct pci_access* pacc, struct pci_dev* dev, uint16_t counter) +{ + char key[8]; + sprintf(key, "GPU%hu", counter); + ffPrintLogoAndKey(state, key); + + char vendor[1048]; + pci_lookup_name(pacc, vendor, sizeof(vendor), PCI_LOOKUP_VENDOR, dev->vendor_id, dev->device_id); + + char name[1048]; + pci_lookup_name(pacc, name, sizeof(name), PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); + + if(strcmp(vendor, "Advanced Micro Devices, Inc. [AMD/ATI]") == 0) + printf("AMD ATI"); + else + printf(vendor); + + printf(" %s\n", name); +} + +void ffPrintGPU(FFstate* state) +{ + uint16_t counter = 0; + + struct pci_access *pacc; + struct pci_dev *dev; + + pacc = pci_alloc(); + pci_init(pacc); + pci_scan_bus(pacc); + for (dev=pacc->devices; dev; dev=dev->next) + { + pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_CLASS); + char class[1024]; + pci_lookup_name(pacc, class, sizeof(class), PCI_LOOKUP_CLASS, dev->device_class); + if( + strcmp("VGA compatible controller", class) == 0 || + strcmp("3D controller", class) == 0 || + strcmp("Display controller", class) == 0 ) + { + handleGPU(state, pacc, dev, counter++); + } + } + pci_cleanup(pacc); +} \ No newline at end of file diff --git a/src/host.c b/src/host.c new file mode 100644 index 000000000..2bc5f0778 --- /dev/null +++ b/src/host.c @@ -0,0 +1,13 @@ +#include "fastfetch.h" + +void ffPrintHost(FFstate* state) +{ + char name[256]; + ffReadFile("/sys/devices/virtual/dmi/id/product_name", name, 256); + + char version[256]; + ffReadFile("/sys/devices/virtual/dmi/id/product_version", version, 256); + + ffPrintLogoAndKey(state, "Host"); + printf("%s %s\n", name, version); +} \ No newline at end of file diff --git a/src/icons.c b/src/icons.c new file mode 100644 index 000000000..520b66caa --- /dev/null +++ b/src/icons.c @@ -0,0 +1,24 @@ +#include "fastfetch.h" + +void ffPrintIcons(FFstate* state) +{ + char plasma[256]; + ffParsePropFileHome(state, ".config/kdeglobals", "Theme=%[^\n]", plasma); + + char gtk2[256]; + ffParsePropFileHome(state, ".gtkrc-2.0", "gtk-icon-theme-name=\"%[^\"]+", gtk2); + + char gtk3[256]; + ffParsePropFileHome(state, ".config/gtk-3.0/settings.ini", "gtk-icon-theme-name=%[^\n]", gtk3); + + char gtk4[256]; + ffParsePropFileHome(state, ".config/gtk-4.0/settings.ini", "gtk-icon-theme-name=%[^\n]", gtk4); + + ffPrintLogoAndKey(state, "Icons"); + + if(plasma[0] != '\0') + printf("%s [Plasma], ", plasma); + + ffPrintGtkPretty(gtk2, gtk3, gtk4); + putchar('\n'); +} \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c new file mode 100644 index 000000000..9caf40142 --- /dev/null +++ b/src/kernel.c @@ -0,0 +1,7 @@ +#include "fastfetch.h" + +void ffPrintKernel(FFstate* state) +{ + ffPrintLogoAndKey(state, "Kernel"); + printf("%s\n", state->utsname.release); +} \ No newline at end of file diff --git a/src/locale.c b/src/locale.c new file mode 100644 index 000000000..23eaac83f --- /dev/null +++ b/src/locale.c @@ -0,0 +1,10 @@ +#include "fastfetch.h" + +void ffPrintLocale(FFstate* state) +{ + char locale[256]; + ffParsePropFile("/etc/locale.conf", "LANG=%[^\n]", locale); + + ffPrintLogoAndKey(state, "Locale"); + puts(locale); +} \ No newline at end of file diff --git a/src/logo.c b/src/logo.c new file mode 100644 index 000000000..7d0cf142c --- /dev/null +++ b/src/logo.c @@ -0,0 +1,98 @@ +#include "fastfetch.h" + +#include + +static void loadArchLogo(FFstate* state) +{ + static const char* chars[] = { + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m -` "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m .o+` "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `ooo/ "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `+oooo: "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `+oooooo: "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m -+oooooo+: "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `/:-:++oooo+: "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `/++++/+++++++: "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `/++++++++++++++: "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `/+++ooooooooooooo/` "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m ./ooosssso++osssssso+` "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m .oossssso-````/ossssss+` "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m -osssssso. :ssssssso. "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m :osssssss/ osssso+++. "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m /ossssssss/ +ssssooo/- "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `/ossssso+/:- -:/+osssso+- "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m `+sso+:-` `.-/+oso: "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m`++:. `-/+/"FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\033[36m.` `/"FASTFETCH_TEXT_MODIFIER_RESET + }; + + state->logo_width = 37; + state->logo_height = 19; + for(uint8_t i = 0; i < state->logo_height; i++) + strcpy(state->logo_chars[i], chars[i]); + strcpy(state->color, "\033[36m"); +} + +static void loadUnknownLogo(FFstate* state) +{ + static const char* chars[] = { + FASTFETCH_TEXT_MODIFIER_BOLT" ________ "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" _jgN########Ngg_ "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" _N##N@@\"\" \"\"9NN##Np_ "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"d###P N####p"FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT"\"^^\" T####"FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" d###P"FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" _g###@F "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" _gN##@P "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" gN###F\" "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" d###F "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" 0###F "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" 0###F "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" 0###F "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" \"NN@' "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" ___ "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" q###r "FASTFETCH_TEXT_MODIFIER_RESET, + FASTFETCH_TEXT_MODIFIER_BOLT" \"\" "FASTFETCH_TEXT_MODIFIER_RESET + }; + + state->logo_width = 23; + state->logo_height = 18; + for(uint8_t i = 0; i < state->logo_height; i++) + strcpy(state->logo_chars[i], chars[i]); + state->color[0] = '\0'; +} + +void ffLoadLogoSet(FFstate* state, const char* logo) +{ + if(strcmp(logo, "arch") == 0) + loadArchLogo(state); + else + loadUnknownLogo(state); +} + +void ffLoadLogo(FFstate* state) +{ + char id[256]; + ffParsePropFile("/etc/os-release", "ID=%[^\n]", id); + + ffLoadLogoSet(state, id); +} + +void ffPrintLogoLine(FFstate* state) +{ + if(state->current_row < state->logo_height) + { + printf(state->logo_chars[state->current_row]); + } + else + { + for(uint8_t i = 0; i < state->logo_width; i++) + putchar(' '); + } + + for(uint8_t i = 0; i < state->logo_seperator; i++) + putchar(' '); + + ++state->current_row; +} diff --git a/src/memory.c b/src/memory.c new file mode 100644 index 000000000..015785a38 --- /dev/null +++ b/src/memory.c @@ -0,0 +1,36 @@ +#include "fastfetch.h" + +// Impl by: https://github.com/sam-barr/paleofetch/blob/b7c58a52c0de39b53c9b5f417889a5886d324bfa/paleofetch.c#L544 +void ffPrintMemory(FFstate* state) +{ + ffPrintLogoAndKey(state, "Memory"); + + FILE *meminfo = fopen("/proc/meminfo", "r"); + if(meminfo == NULL) { + printf("[Error opening /proc/meminfo\n"); + return; + } + + char *line = NULL; + size_t len; + + uint32_t total, shared, memfree, buffers, cached, reclaimable; + + while (getline(&line, &len, meminfo) != -1) { + sscanf(line, "MemTotal: %lu", &total); + sscanf(line, "Shmem: %lu", &shared); + sscanf(line, "MemFree: %lu", &memfree); + sscanf(line, "Buffers: %lu", &buffers); + sscanf(line, "Cached: %lu", &cached); + sscanf(line, "SReclaimable: %lu", &reclaimable); + } + + free(line); + fclose(meminfo); + + uint32_t used_mem = (total + shared - memfree - buffers - cached - reclaimable) / 1024; + uint32_t total_mem = total / 1024; + uint8_t percentage = (uint8_t) ((used_mem / (double) total_mem) * 100); + + printf("%luMiB / %luMiB (%u%%)\n", used_mem, total_mem, percentage); +} \ No newline at end of file diff --git a/src/os.c b/src/os.c new file mode 100644 index 000000000..49c39fb04 --- /dev/null +++ b/src/os.c @@ -0,0 +1,24 @@ +#include "fastfetch.h" + +void ffPrintOS(FFstate* state) +{ + char* line = NULL; + char name[256]; + size_t len; + + FILE* os_release = fopen("/etc/os-release", "r"); + if(os_release == NULL) + exit(2); + + while (getline(&line, &len, os_release) != -1) + { + if (sscanf(line, "NAME=\"%[^\"]+", name) > 0) + break; + } + + fclose(os_release); + free(line); + + ffPrintLogoAndKey(state, "OS"); + printf("%s %s\n", name, state->utsname.machine); +} \ No newline at end of file diff --git a/src/packages.c b/src/packages.c new file mode 100644 index 000000000..459dc4be5 --- /dev/null +++ b/src/packages.c @@ -0,0 +1,40 @@ +#include "fastfetch.h" + +#include + +static uint32_t get_num_dirs(const char* dirname) { + uint32_t num_dirs = 0; + DIR * dirp; + struct dirent *entry; + + dirp = opendir(dirname); + if(dirp == NULL) { + fprintf(stderr, "Error opening directory: %s\n", dirname); + } + + while((entry = readdir(dirp)) != NULL) { + if(entry->d_type == DT_DIR) + ++num_dirs; + } + + num_dirs -= 2; // accounting for . and .. + + closedir(dirp); + + return num_dirs; +} + + +static void printPacmanPackages() +{ + uint32_t nums = get_num_dirs("/var/lib/pacman/local"); + if(nums > 0) + printf("%i (pacman) ", nums); +} + +void ffPrintPackages(FFstate* state) +{ + ffPrintLogoAndKey(state, "Packages"); + printPacmanPackages(); + putchar('\n'); +} \ No newline at end of file diff --git a/src/resolution.c b/src/resolution.c new file mode 100644 index 000000000..60df7e376 --- /dev/null +++ b/src/resolution.c @@ -0,0 +1,13 @@ +#include "fastfetch.h" + +#include + +void ffPrintResolution(FFstate* state) +{ + + Display* display = XOpenDisplay(NULL); + Screen* screen = DefaultScreenOfDisplay(display); + + ffPrintLogoAndKey(state, "Resolution"); + printf("%ix%i\n", screen->width, screen->height); +} \ No newline at end of file diff --git a/src/seperator.c b/src/seperator.c new file mode 100644 index 000000000..71de3a09a --- /dev/null +++ b/src/seperator.c @@ -0,0 +1,10 @@ +#include "fastfetch.h" + +void ffPrintSeperator(FFstate* state) +{ + ffPrintLogoLine(state); + + for(uint8_t i = 0; i < state->titleLength; i++) + putchar('-'); + putchar('\n'); +} \ No newline at end of file diff --git a/src/shell.c b/src/shell.c new file mode 100644 index 000000000..b3c302d94 --- /dev/null +++ b/src/shell.c @@ -0,0 +1,17 @@ +#include "fastfetch.h" + +#include + +void ffPrintShell(FFstate* state) +{ + char* shellPath = getenv("SHELL"); + char* shellName = strrchr(shellPath, '/'); + + if(shellName == NULL) + shellName = shellPath; + else if(shellName[0] == '/') + ++shellName; + + ffPrintLogoAndKey(state, "Shell"); + printf("%s\n", shellName); +} \ No newline at end of file diff --git a/src/terminal.c b/src/terminal.c new file mode 100644 index 000000000..4f0abe8e3 --- /dev/null +++ b/src/terminal.c @@ -0,0 +1,56 @@ +#include "fastfetch.h" + +#include + +void printTerminalName(const char* pid) +{ + char file[256]; + sprintf(file, "/proc/%s/stat", pid); + + FILE* stat = fopen(file, "r"); + if(stat == NULL) + { + printf("[Error opening %s]", file); + return; + } + + char name[256]; + char ppid[256]; + + fscanf(stat, "%*s (%[^)])%*s%s", name, ppid); + + fclose(stat); + + if ( + strcmp(name, "bash") == 0 || + strcmp(name, "sh") == 0 || + strcmp(name, "zsh") == 0 || + strcmp(name, "ksh") == 0 || + strcmp(name, "fish") == 0 || + strcmp(name, "sudo") == 0 || + strcmp(name, "su") == 0 || + strcmp(name, "doas") == 0 ) + { + printTerminalName(ppid); + } + else if( + strcmp(name, "systemd") == 0 || + strcmp(name, "init") == 0 || + strcmp(ppid, "0") == 0 ) + { + puts("TTY"); + } + else + { + printf("%s\n", name); + } +} + +void ffPrintTerminal(FFstate* state) +{ + char ppid[256]; + sprintf(ppid, "%i", getppid()); + + ffPrintLogoAndKey(state, "Terminal"); + printTerminalName(ppid); +} diff --git a/src/theme.c b/src/theme.c new file mode 100644 index 000000000..1b76f3981 --- /dev/null +++ b/src/theme.c @@ -0,0 +1,24 @@ +#include "fastfetch.h" + +void ffPrintTheme(FFstate* state) +{ + char plasma[256]; + ffParsePropFileHome(state, ".config/kdeglobals", "Name=%[^\n]", plasma); + + char gtk2[256]; + ffParsePropFileHome(state, ".gtkrc-2.0", "gtk-theme-name=\"%[^\"]+", gtk2); + + char gtk3[256]; + ffParsePropFileHome(state, ".config/gtk-3.0/settings.ini", "gtk-theme-name=%[^\n]", gtk3); + + char gtk4[256]; + ffParsePropFileHome(state, ".config/gtk-4.0/settings.ini", "gtk-theme-name=%[^\n]", gtk4); + + ffPrintLogoAndKey(state, "Theme"); + + if(plasma[0] != '\0') + printf("%s [Plasma], ", plasma); + + ffPrintGtkPretty(gtk2, gtk3, gtk4); + putchar('\n'); +} \ No newline at end of file diff --git a/src/title.c b/src/title.c new file mode 100644 index 000000000..9e5e1bfee --- /dev/null +++ b/src/title.c @@ -0,0 +1,17 @@ +#include "fastfetch.h" + +#include + +void ffPrintTitle(FFstate* state) +{ + char hostname[256]; + gethostname(hostname, 256); + + state->titleLength = strlen(state->passwd->pw_name) + 1 + strlen(hostname); + + ffPrintLogoLine(state); + + printf("%s"FASTFETCH_TEXT_MODIFIER_BOLT"%s"FASTFETCH_TEXT_MODIFIER_RESET"@%s"FASTFETCH_TEXT_MODIFIER_BOLT"%s"FASTFETCH_TEXT_MODIFIER_RESET"\n", + state->color, state->passwd->pw_name, state->color, hostname + ); +} \ No newline at end of file diff --git a/src/uptime.c b/src/uptime.c new file mode 100644 index 000000000..7c43ee95c --- /dev/null +++ b/src/uptime.c @@ -0,0 +1,19 @@ +#include "fastfetch.h" + +void ffPrintUptime(FFstate* state) +{ + + int days = state->sysinfo.uptime / 86400; + int hours = (state->sysinfo.uptime - (days * 86400)) / 3600; + int minutes = (state->sysinfo.uptime - (days * 86400) - (hours * 3600)) / 60; + + ffPrintLogoAndKey(state, "Uptime"); + + if(days > 0) + printf("%d day%s, ", days, days <= 1 ? "" : "s"); + + if(hours > 0) + printf("%d hour%s, ", hours, hours <= 1 ? "" : "s"); + + printf("%d min%s\n", minutes, minutes <= 1 ? "" : "s"); +} \ No newline at end of file