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