| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- #ifdef __OpenBSD__
- #define _BSD_SOURCE
- #else
- #define _POSIX_C_SOURCE 200809L
- #endif
- #include <pwd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <strings.h>
- #include <sys/types.h>
- #include <sys/utsname.h>
- #include <time.h>
- #include <unistd.h>
- #ifdef __OpenBSD__
- #include <getopt.h>
- #endif
- #ifdef __linux__
- #include <sys/sysinfo.h>
- #endif
- #ifdef __OpenBSD__
- #include <sys/param.h>
- #include <sys/sysctl.h>
- #include <sys/time.h>
- #include <uvm/uvm_extern.h>
- #endif
- #include "ascii"
- /* sizes */
- #define MAXLINE 256
- #define BUFSIZE 512
- #define CLR_RESET "\033[0m"
- #define CLR_BLUE "\033[1;34m"
- #define CLR_CYAN "\033[1;36m"
- #define CLR_GREEN "\033[1;32m"
- #define CLR_MAGENTA "\033[1;35m"
- #define CLR_RED "\033[1;31m"
- #define CLR_WHITE "\033[1;37m"
- #define CLR_YELLOW "\033[1;33m"
- #define LEN(x) (sizeof(x) / sizeof(*(x)))
- #define MAXIMUM(a,b) ((a) > (b) ? (a) : (b))
- #define UNKNOWN(buf) sset((buf), sizeof(buf), "unknown")
- #define APPEND(buf, fmt, ...) \
- do { \
- size_t __off = strlen(buf); \
- if (__off < sizeof(buf)) \
- snprintf((buf) + __off, sizeof(buf) - __off, fmt, __VA_ARGS__); \
- } while (0)
- #ifdef __OpenBSD__
- static int sysctl_hw (const char *, void *, size_t *);
- #endif
- struct Info
- {
- char hostname[MAXLINE], kernel[MAXLINE], uptime[MAXLINE];
- char cpu[MAXLINE], memory[MAXLINE], load[MAXLINE];
- char distro[MAXLINE], shell[MAXLINE], terminal[MAXLINE], user[MAXLINE];
- };
- struct AsciiEntry
- {
- const char *needle;
- const char **art;
- const char *color;
- };
- static void sset (char *, size_t, const char *);
- static void usage (void);
- static void hostname (struct Info *);
- static void kernel (struct Info *);
- static void uptime (struct Info *);
- static void cpu (struct Info *);
- static void memory (struct Info *);
- static void load (struct Info *);
- static void distro (struct Info *);
- static void shell (struct Info *);
- static void terminal (struct Info *);
- static void user (struct Info *);
- static void collect (struct Info *);
- static void display (struct Info *, int, int, char *);
- static const char **asciisel (const char *, const char **);
- static int asciimatch (const char *, const char *);
- static char *argv0;
- static const struct AsciiEntry ascii_entries[] = {
- {"alpine", ascii_alpine, CLR_CYAN},
- {"android", ascii_android, CLR_GREEN},
- {"arch", ascii_arch, CLR_CYAN},
- {"arco", ascii_arco, CLR_BLUE},
- {"artix", ascii_artix, CLR_CYAN},
- {"centos", ascii_centos, CLR_MAGENTA},
- {"debian", ascii_debian, CLR_RED},
- {"endeavour", ascii_endeavour, CLR_MAGENTA},
- {"fedora", ascii_fedora, CLR_BLUE},
- {"freebsd", ascii_freebsd, CLR_RED},
- {"gentoo", ascii_gentoo, CLR_MAGENTA},
- {"linux mint", ascii_linux_mint, CLR_GREEN},
- {"macos", ascii_macos, CLR_WHITE},
- {"mac os", ascii_macos, CLR_WHITE},
- {"manjaro", ascii_manjaro, CLR_GREEN},
- {"nixos", ascii_nixos, CLR_BLUE},
- {"openbsd", ascii_openbsd, CLR_YELLOW},
- {"opensuse", ascii_opensuse, CLR_GREEN},
- {"pop!_os", ascii_pop_os, CLR_CYAN},
- {"pop os", ascii_pop_os, CLR_CYAN},
- {"slackware", ascii_slackware, CLR_BLUE},
- {"solus", ascii_solus, CLR_BLUE},
- {"ubuntu", ascii_ubuntu, CLR_MAGENTA},
- {"void", ascii_void, CLR_GREEN},
- {"linux", ascii_linux, CLR_WHITE}
- };
- static void
- sset (char *dst, size_t dstsz, const char *src)
- {
- if (!dstsz)
- return;
- #ifdef __OpenBSD__
- strlcpy (dst, src, dstsz);
- #else
- snprintf (dst, dstsz, "%s", src);
- #endif
- }
- #ifdef __OpenBSD__
- static int
- sysctl_hw (const char *name, void *out, size_t *lenp)
- {
- int mib[2];
- int miblen = 2;
- if (!strcmp (name, "hw.model")) {
- mib[0] = CTL_HW;
- mib[1] = HW_MODEL;
- }
- else if (!strcmp (name, "hw.ncpu")) {
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- }
- else if (!strcmp (name, "hw.physmem64")) {
- mib[0] = CTL_HW;
- mib[1] = HW_PHYSMEM64;
- }
- else {
- return -1;
- }
- return sysctl (mib, (u_int) miblen, out, lenp, NULL, 0);
- }
- #endif
- static void
- usage (void)
- {
- fprintf (stderr, "usage: %s [-m] [-s] [-k key] [-h] [-v]\n", argv0);
- exit (1);
- }
- static void
- hostname (struct Info *i)
- {
- if (gethostname (i->hostname, sizeof (i->hostname)) < 0)
- UNKNOWN (i->hostname);
- }
- static void
- kernel (struct Info *i)
- {
- struct utsname u;
- if (uname (&u) < 0 || !*u.sysname)
- UNKNOWN (i->kernel);
- else
- snprintf (i->kernel, sizeof (i->kernel), "%s %s", u.sysname, u.release);
- }
- static void
- uptime (struct Info *i)
- {
- #if defined(__linux__)
- struct sysinfo s;
- int d, h, m;
- if (sysinfo (&s) < 0) {
- UNKNOWN (i->uptime);
- return;
- }
- d = s.uptime / 86400;
- h = (s.uptime % 86400) / 3600;
- m = (s.uptime % 3600) / 60;
- #elif defined(__OpenBSD__)
- struct timeval boottime;
- time_t now, up;
- int mib[2] = { CTL_KERN, KERN_BOOTTIME };
- size_t size = sizeof (boottime);
- int d, h, m;
- if (sysctl (mib, 2, &boottime, &size, NULL, 0) < 0 || !boottime.tv_sec) {
- UNKNOWN (i->uptime);
- return;
- }
- if ((now = time (NULL)) == (time_t) - 1) {
- UNKNOWN (i->uptime);
- return;
- }
- up = now - boottime.tv_sec;
- if (up < 0)
- up = 0;
- d = up / 86400;
- h = (up % 86400) / 3600;
- m = (up % 3600) / 60;
- #else
- UNKNOWN (i->uptime);
- return;
- #endif
- if (d)
- snprintf (i->uptime, sizeof (i->uptime), "%dd %dh %dm", d, h, m);
- else if (h)
- snprintf (i->uptime, sizeof (i->uptime), "%dh %dm", h, m);
- else
- snprintf (i->uptime, sizeof (i->uptime), "%dm", m);
- }
- static void
- cpu (struct Info *i)
- {
- #if defined(__linux__)
- FILE *f;
- char buf[BUFSIZE], model[MAXLINE] = "unknown";
- int cores = 0;
- if (!(f = fopen ("/proc/cpuinfo", "r"))) {
- UNKNOWN (i->cpu);
- return;
- }
- while (fgets (buf, sizeof (buf), f))
- if (!strncmp (buf, "model name", 10)) {
- if ((buf[strcspn (buf, "\n")] = 0, strchr (buf, ':')))
- sset (model, sizeof (model), strchr (buf, ':') + 2);
- }
- else if (!strncmp (buf, "processor", 9))
- cores++;
- fclose (f);
- sset (i->cpu, sizeof (i->cpu), model);
- if (cores)
- APPEND (i->cpu, " (%d cores)", cores);
- #elif defined(__OpenBSD__)
- char model[MAXLINE] = "unknown";
- int cores = 0;
- size_t len;
- len = sizeof (model);
- if (sysctl_hw ("hw.model", model, &len) == -1 || !*model) {
- UNKNOWN (i->cpu);
- return;
- }
- len = sizeof (cores);
- if (sysctl_hw ("hw.ncpu", &cores, &len) == -1)
- cores = 0;
- sset (i->cpu, sizeof (i->cpu), model);
- if (cores > 0)
- APPEND (i->cpu, " (%d cores)", cores);
- #else
- UNKNOWN (i->cpu);
- #endif
- }
- static void
- memory (struct Info *i)
- {
- #if defined(__linux__)
- FILE *f;
- char buf[BUFSIZE];
- long total = 0, avail = 0;
- if (!(f = fopen ("/proc/meminfo", "r"))) {
- UNKNOWN (i->memory);
- return;
- }
- while (fgets (buf, sizeof (buf), f) && (!total || !avail))
- if (!strncmp (buf, "MemTotal:", 9))
- sscanf (buf, "MemTotal: %ld", &total);
- else if (!strncmp (buf, "MemAvailable:", 13))
- sscanf (buf, "MemAvailable: %ld", &avail);
- fclose (f);
- if (total && avail) {
- long used = (total - avail) / 1024;
- long tmb = total / 1024;
- snprintf (i->memory, sizeof (i->memory), "%ld/%ld MB", used, tmb);
- }
- else {
- UNKNOWN (i->memory);
- }
- #elif defined(__OpenBSD__)
- int mib[2];
- struct uvmexp uvmexp;
- unsigned long long total, used;
- size_t len;
- long pagesize;
- mib[0] = CTL_HW;
- mib[1] = HW_PHYSMEM64;
- len = sizeof (total);
- if (sysctl (mib, 2, &total, &len, NULL, 0) == -1) {
- UNKNOWN (i->memory);
- return;
- }
- mib[0] = CTL_VM;
- mib[1] = VM_UVMEXP;
- len = sizeof (uvmexp);
- if (sysctl (mib, 2, &uvmexp, &len, NULL, 0) == -1) {
- UNKNOWN (i->memory);
- return;
- }
- if ((pagesize = sysconf (_SC_PAGESIZE)) <= 0) {
- UNKNOWN (i->memory);
- return;
- }
- used =
- (unsigned long long) (uvmexp.active +
- uvmexp.wired) * (unsigned long long) pagesize;
- snprintf (i->memory, sizeof (i->memory), "%llu/%llu MiB",
- used / (1024ULL * 1024ULL), total / (1024ULL * 1024ULL));
- #else
- UNKNOWN (i->memory);
- #endif
- }
- static void
- load (struct Info *i)
- {
- #if defined(__linux__)
- struct sysinfo s;
- if (sysinfo (&s) < 0) {
- UNKNOWN (i->load);
- return;
- }
- snprintf (i->load, sizeof (i->load), "%.2f %.2f %.2f",
- s.loads[0] / 65536.0, s.loads[1] / 65536.0, s.loads[2] / 65536.0);
- #elif defined(__OpenBSD__)
- double loadavg[3];
- if (getloadavg (loadavg, 3) == -1) {
- UNKNOWN (i->load);
- return;
- }
- snprintf (i->load, sizeof (i->load), "%.2f %.2f %.2f",
- loadavg[0], loadavg[1], loadavg[2]);
- #else
- UNKNOWN (i->load);
- #endif
- }
- static void
- distro (struct Info *i)
- {
- FILE *f;
- char buf[BUFSIZE], *p, *q;
- *i->distro = 0;
- if ((f = fopen ("/etc/os-release", "r"))) {
- while (fgets (buf, sizeof (buf), f))
- if (!strncmp (buf, "PRETTY_NAME=", 12) && (p = strchr (buf, '"'))) {
- if ((q = strchr (++p, '"'))) {
- *q = 0;
- sset (i->distro, sizeof (i->distro), p);
- break;
- }
- }
- fclose (f);
- }
- if (!*i->distro && (f = fopen ("/etc/issue", "r"))) {
- if (fgets (buf, sizeof (buf), f)) {
- buf[strcspn (buf, "\n\\\\")] = 0;
- sset (i->distro, sizeof (i->distro), buf);
- }
- fclose (f);
- }
- if (!*i->distro) {
- struct utsname u;
- if (uname (&u) == 0 && *u.sysname)
- sset (i->distro, sizeof (i->distro), u.sysname);
- else
- UNKNOWN (i->distro);
- }
- }
- static void
- shell (struct Info *i)
- {
- char *s, *b;
- if (!(s = getenv ("SHELL"))) {
- UNKNOWN (i->shell);
- return;
- }
- sset (i->shell, sizeof (i->shell), (b = strrchr (s, '/')) ? b + 1 : s);
- }
- static void
- terminal (struct Info *i)
- {
- char *t = getenv ("TERM");
- if (!t) {
- UNKNOWN (i->terminal);
- return;
- }
- sset (i->terminal, sizeof (i->terminal), t);
- }
- static void
- user (struct Info *i)
- {
- struct passwd *p = getpwuid (getuid ());
- if (!p || !p->pw_name) {
- UNKNOWN (i->user);
- return;
- }
- sset (i->user, sizeof (i->user), p->pw_name);
- }
- static void
- collect (struct Info *i)
- {
- hostname (i);
- kernel (i);
- uptime (i);
- cpu (i);
- memory (i);
- load (i);
- distro (i);
- shell (i);
- terminal (i);
- user (i);
- }
- static void
- display (struct Info *i, int m, int s, char *k)
- {
- char *sep;
- struct
- {
- char *name, *val;
- } fields[] = {
- {"user", i->user}, {"hostname", i->hostname}, {"distro", i->distro},
- {"kernel", i->kernel}, {"uptime", i->uptime}, {"shell", i->shell},
- {"terminal", i->terminal}, {"cpu", i->cpu}, {"memory", i->memory},
- {"load", i->load}
- }, short_fields[] = {
- {"hostname", i->hostname}, {"kernel", i->kernel}, {"uptime", i->uptime},
- {"memory", i->memory}
- };
- const char **ascii;
- const char *color, *line;
- int n, j, ascii_lines, ascii_width, max_lines, len, pad;
- int total, short_total;
- sep = m ? "|" : ": ";
- total = LEN (fields);
- short_total = LEN (short_fields);
- if (k) {
- for (j = 0; j < total; j++)
- if (!strcmp (k, fields[j].name)) {
- printf ("%s\n", fields[j].val);
- return;
- }
- return;
- }
- ascii = asciisel (i->distro, &color);
- ascii_lines = 0;
- ascii_width = 0;
- if (ascii) {
- for (j = 0; ascii[j]; j++) {
- len = (int) strlen (ascii[j]);
- if (len > ascii_width)
- ascii_width = len;
- }
- ascii_lines = j;
- }
- n = s ? short_total : total;
- max_lines = MAXIMUM (ascii_lines, n);
- for (j = 0; j < max_lines; j++) {
- len = 0;
- pad = ascii_width;
- if (j < ascii_lines) {
- line = ascii[j];
- len = (int) strlen (line);
- pad = ascii_width - len;
- if (pad < 0)
- pad = 0;
- printf ("%s%s%s", color, line, CLR_RESET);
- if (pad)
- printf ("%*s", pad, "");
- }
- else if (ascii_width) {
- printf ("%*s", ascii_width, "");
- }
- printf (" ");
- if (j < n)
- printf ("%s%s%s", (s ? short_fields : fields)[j].name, sep,
- (s ? short_fields : fields)[j].val);
- putchar ('\n');
- }
- }
- static const char **
- asciisel (const char *distro, const char **color)
- {
- int idx, count;
- count = (int) LEN (ascii_entries);
- for (idx = 0; idx < count; idx++)
- if (asciimatch (distro, ascii_entries[idx].needle)) {
- *color = ascii_entries[idx].color;
- return ascii_entries[idx].art;
- }
- *color = CLR_WHITE;
- return ascii_linux;
- }
- static int
- asciimatch (const char *distro, const char *needle)
- {
- size_t len;
- const char *p;
- if (!distro || !needle)
- return 0;
- len = strlen (needle);
- if (!len)
- return 0;
- for (p = distro; *p; p++)
- if (!strncasecmp (p, needle, len))
- return 1;
- return 0;
- }
- int
- main (int argc, char **argv)
- {
- struct Info info = { 0 };
- int m = 0, s = 0, c;
- char *k = NULL;
- for (argv0 = *argv; (c = getopt (argc, argv, "msk:hv")) != -1;)
- switch (c) {
- case 'm':
- m = 1;
- break;
- case 's':
- s = 1;
- break;
- case 'k':
- k = optarg;
- break;
- case 'h':
- usage ();
- break;
- case 'v':
- puts ("ssf 1.0");
- exit (0);
- default:
- usage ();
- }
- collect (&info);
- display (&info, m, s, k);
- return 0;
- }
|