From 4155ac253b77ff736a1fd32ef61dde15f636b16a Mon Sep 17 00:00:00 2001 From: su8 Date: Sat, 4 Aug 2018 22:26:40 +0200 Subject: [PATCH] Add new text objects to retrieve the currently used keyboard layout and mouse speed in percentage and generate random password of chosen length and get the cpu clock speed from assembly --- src/CMakeLists.txt | 1 + src/conky.cc | 31 ++++------ src/core.cc | 16 +++++ src/cpu.cc | 148 +++++++++++++++++++++++++++++++++++++++++++++ src/cpu.h | 40 ++++++++++++ src/entropy.cc | 19 ++++++ src/entropy.h | 1 + src/journal.cc | 14 +++++ src/x11.cc | 26 ++++++++ src/x11.h | 4 ++ 10 files changed, 280 insertions(+), 20 deletions(-) create mode 100644 src/cpu.cc create mode 100644 src/cpu.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0b07fc0a..59d2efba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,6 +44,7 @@ set(conky_sources common.cc common.h conky.cc conky.h core.cc core.h + cpu.cc cpu.h diskio.cc diskio.h entropy.cc entropy.h exec.cc exec.h diff --git a/src/conky.cc b/src/conky.cc index a1c81bee..e09a40c4 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include "common.h" #include "config.h" #include "conky.h" @@ -1990,29 +1989,21 @@ static void update_text() { int inotify_fd = -1; #endif -template -void split(const std::string &s, char delim, Out result) { - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) { - *(result++) = item; - } -} - -std::vector split(const std::string &s, char delim) { - std::vector elems; - split(s, delim, std::back_inserter(elems)); - return elems; -} - bool is_on_battery() { // checks if at least one battery specified in // "detect_battery" is discharging char buf[64]; - std::vector b_items = split(detect_battery.get(*state), ','); + std::string detect_battery_str; + std::string str_buf = str_buf; + detect_battery_str.assign(detect_battery.get(*state)); + detect_battery_str += ','; - for(auto const& value: b_items) { - get_battery_short_status(buf, 64, value.c_str()); - if (buf[0] == 'D') { return true; } + for (char i : detect_battery_str) { // parse using ',' as delimiter + if ((i != ',') && (i != ' ')) { str_buf += i; } + if ((i == ',') && !str_buf.empty()) { + get_battery_short_status(buf, 64, str_buf.c_str()); + if (buf[0] == 'D') { return true; } + str_buf = ""; + } } return false; } diff --git a/src/core.cc b/src/core.cc index 1c6936ef..0ef886ea 100644 --- a/src/core.cc +++ b/src/core.cc @@ -84,6 +84,8 @@ #include "top.h" #include "user.h" #include "users.h" +#include +#include "cpu.h" #ifdef BUILD_CURL #include "ccurl_thread.h" #endif /* BUILD_CURL */ @@ -823,8 +825,22 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &print_caps_led; END OBJ(scroll_led, 0) obj->callbacks.print = &print_scroll_led; + END OBJ(kb_layout, 0) + obj->callbacks.print = &print_kb_layout; + END OBJ(mouse_speed, 0) + obj->callbacks.print = &print_mouse_speed; #endif /* BUILD_X11 */ + END OBJ(password, 0) + obj->data.s = strndup(arg ? arg : "", text_buffer_size.get(*state)); + obj->callbacks.print = &print_password; + obj->callbacks.free = &gen_free_opaque; + + #ifdef __x86_64__ + END OBJ(freq2, 0) + obj->callbacks.print = &print_freq2; +#endif /* __x86_64__ */ + END OBJ(cap, 0) obj->data.s = strndup(arg ? arg : "", text_buffer_size.get(*state)); obj->callbacks.print = &print_cap; diff --git a/src/cpu.cc b/src/cpu.cc new file mode 100644 index 00000000..5a8fbcd0 --- /dev/null +++ b/src/cpu.cc @@ -0,0 +1,148 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2018 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "config.h" +#include "conky.h" +#include "text_object.h" +#include +#include +#include +#include +#include +#include + +#ifdef __x86_64__ +#define CPU_FEATURE(x, z) __asm__ __volatile__("cpuid": "=a" (z) : "a" (x)) +#define CPU_REGS(x, y, z) __asm__ __volatile__ ( \ + "cpuid": \ + "=a" (z), \ + "=b" (y) \ + : "a" (x) \ +) +#define CPU_STR2(regizter, a, b, c, d) __asm__ __volatile__ ( \ + "cpuid": \ + "=a" (a), \ + "=b" (b), \ + "=c" (c), \ + "=d" (d) \ + : "a" (regizter) \ +) + +#define AmD 0x68747541 +#define InteL 0x756e6547 +#define FMT_UINT "%" PRIuMAX + +#if defined(__FreeBSD__) +# define TICKZ 100L +#else +# define TICKZ sysconf(_SC_CLK_TCK) +#endif /* __FreeBSD__ */ + +uint8_t has_tsc_reg(void) { + uint_fast16_t vend = 0, leafs = 0; + uint_fast16_t eax = 0, ecx = 0, edx = 0, ebx = 0; + + CPU_REGS(0x00000000, vend, leafs); + if (0x00000001 > leafs) { + return 1U; + } + if (vend != AmD && vend != InteL) { + return 1U; + } + + CPU_STR2(0x00000001, eax, ebx, ecx, edx); + if (0U == (edx & (1U << 4U))) { + return 1U; + } + return 0U; +} + +uintmax_t rdtsc(void) { + unsigned int tickhi = 0, ticklo = 0; + uint_fast16_t eax = 0, ecx = 0, edx = 0, ebx = 0; + uint_fast16_t regz = 0, x = 0; + + if (0U != (has_tsc_reg())) { + goto seeya; + } + __asm__ __volatile__ ( + "cpuid\n\t" + "rdtsc\n\t" + : "=a"(ticklo), "=d"(tickhi) + :: "%rbx", "%rcx" + ); + + CPU_FEATURE(0x80000000, regz); + if (0x80000001 > regz) { + goto seeya; + } + CPU_STR2(0x80000001, eax, ebx, ecx, edx); + + if (0U != (edx & (1U << 27U))) { + for (x = 0; x < 6U; x++) { + __asm__ __volatile__ ( + "rdtscp\n\t" + "mov %%edx, %0\n\t" + "mov %%eax, %1\n\t" + "cpuid\n\t" + : "=r"(tickhi), "=r"(ticklo) + :: "%rax", "%rbx", "%rcx", "%rdx" + ); + } + } + +seeya: + return (((uintmax_t)tickhi << 32) | (uintmax_t)ticklo); +} + +void +get_cpu_clock_speed(char *str1, int p_max_size) { + uintmax_t x = 0, z = 0; + struct timespec tc = {0L, 0L}; + + tc.tv_nsec = TICKZ * 1000000L; + + x = rdtsc(); + if (-1 == (nanosleep(&tc, NULL))) { + return; + } + z = rdtsc(); + + snprintf(str1, p_max_size, FMT_UINT " MHz", ((z - x) / 100000U)); +} + +void print_freq2(struct text_object *obj, char *p, int p_max_size) { + (void)obj; + get_cpu_clock_speed(p, p_max_size); + return; +} + +#else +char *l337; +#endif /* __x86_64__ */ diff --git a/src/cpu.h b/src/cpu.h new file mode 100644 index 00000000..0b588b99 --- /dev/null +++ b/src/cpu.h @@ -0,0 +1,40 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2018 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef _CPU_H +#define _CPU_H + +#ifdef __x86_64__ +uintmax_t rdtsc(void); +void get_cpu_clock_speed(char *, int); +uint8_t has_tsc_reg(void); +void print_freq2(struct text_object *, char *, int); +#endif /* __x86_64__ */ + +#endif /* _CPU_H */ diff --git a/src/entropy.cc b/src/entropy.cc index 9884b262..add1c4d0 100644 --- a/src/entropy.cc +++ b/src/entropy.cc @@ -30,6 +30,8 @@ #include "config.h" #include "conky.h" #include "text_object.h" +#include +#include /* check for OS and include appropriate headers */ #if defined(__linux__) @@ -83,3 +85,20 @@ double entropy_barval(struct text_object *obj) { return static_cast(entropy.avail) / entropy.poolsize; } + +void print_password(struct text_object *obj, char *p, int p_max_size) { + time_t t; + static const char letters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_"; + static const int len = (int)sizeof(letters) - 1; + uintmax_t x = strtoumax(obj->data.s, (char **)NULL, 10), z = 0; + + if (-1 == (t = time(NULL))) { + return; + } + srandom((unsigned int)t); + + for (; z < x && p_max_size-1 > z; z++) { + *p++ = letters[random() % len]; + } + *p = '\0'; +} diff --git a/src/entropy.h b/src/entropy.h index 481452f9..9f3444d6 100644 --- a/src/entropy.h +++ b/src/entropy.h @@ -36,5 +36,6 @@ void print_entropy_avail(struct text_object *, char *, int); uint8_t entropy_percentage(struct text_object *); void print_entropy_poolsize(struct text_object *, char *, int); double entropy_barval(struct text_object *); +void print_password(struct text_object *, char *, int); #endif /* _ENTROPY_H */ diff --git a/src/journal.cc b/src/journal.cc index 5e694c29..c52bf784 100644 --- a/src/journal.cc +++ b/src/journal.cc @@ -129,6 +129,11 @@ bool read_log(size_t *read, size_t *length, time_t *time, uint64_t *timestamp, strftime(p + *read, p_max_size - *read, "%b %d %H:%M:%S", &tm)) <= 0) return false; *read += *length; + + if (p_max_size < *read) { + *read = p_max_size - 1; + return false; + } p[*read++] = ' '; if (print_field(jh, "_HOSTNAME", ' ', read, p, p_max_size) < 0) return false; @@ -138,7 +143,16 @@ bool read_log(size_t *read, size_t *length, time_t *time, uint64_t *timestamp, if (print_field(jh, "_PID", ']', read, p, p_max_size) < 0) return false; + if (p_max_size < *read) { + *read = p_max_size - 1; + return false; + } p[*read++] = ':'; + + if (p_max_size < *read) { + *read = p_max_size - 1; + return false; + } p[*read++] = ' '; if (print_field(jh, "MESSAGE", '\n', read, p, p_max_size) < 0) return false; diff --git a/src/x11.cc b/src/x11.cc index 58a05e54..71b9eaab 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef BUILD_IMLIB2 #include "imlib2.h" #endif /* BUILD_IMLIB2 */ @@ -1313,3 +1314,28 @@ void print_##func(struct text_object *obj, char *p, int p_max_size) { \ LOCK_TEMPLATE(num_led, 2) LOCK_TEMPLATE(caps_led, 1) LOCK_TEMPLATE(scroll_led, 4) + +void print_kb_layout(struct text_object *obj, char *p, int p_max_size) { + (void)obj; + + char *group = NULL; + XkbStateRec state; + XkbDescPtr desc; + + XkbGetState(display, XkbUseCoreKbd, &state); + desc = XkbGetKeyboard(display, XkbAllComponentsMask, XkbUseCoreKbd); + group = XGetAtomName(display, desc->names->groups[state.group]); + + snprintf(p, p_max_size, "%s", (group != NULL ? group : "unknown")); + XFree(group); + return; +} + +void print_mouse_speed(struct text_object *obj, char *p, int p_max_size) { + (void)obj; + int acc_num = 0, acc_denom = 0, threshold = 0; + + XGetPointerControl(display, &acc_num, &acc_denom, &threshold); + snprintf(p, p_max_size, "%d%%", (110 - threshold)); + return; +} diff --git a/src/x11.h b/src/x11.h index 94c22da3..b1d2b46b 100644 --- a/src/x11.h +++ b/src/x11.h @@ -120,6 +120,10 @@ void print_num_led(struct text_object *, char *, int); void print_caps_led(struct text_object *, char *, int); void print_scroll_led(struct text_object *, char *, int); +/* Keyboard layout and mouse speed in percentage */ +void print_kb_layout(struct text_object *, char *, int); +void print_mouse_speed(struct text_object *, char *, int); + #ifdef BUILD_XDBE void xdbe_swap_buffers(void); #else