diff --git a/src/cpu.c b/src/cpu.c new file mode 100644 index 0000000..b14ba35 --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,39 @@ +#include "cpu.h" + +#include +#include +#include +#include + +char const* const cpu_path = "/sys/devices/system/cpu/cpu%i/online"; + +bool getcore(uint32_t id) { + // get the file path + char path[64]; // contains the file path (max length is 64 due to the path and a bunch of extra wiggle room) + snprintf(path, 64, cpu_path, id); // writes the path using the id + + // if the file doesn't exist; return true + if (access(path, R_OK) != 0) + return true; + + // read a character from the file, store in state + char state = '\0'; + FILE* f = fopen(path, "r"); + fread(&state, 1, 1, f); + fclose(f); + + // return whether state is truthy + return !!state; +} + +void setcore(uint32_t id, bool state) { + char path[64]; + snprintf(path, 64, cpu_path, id); + + char s = 0x30 + (char)state; // convert the state to a character + + // write the state to the file (creates file if it doesn't exist) + FILE* f = fopen(path, "w"); + fwrite(&s, 1, 1, f); + fclose(f); +} diff --git a/src/cpu.h b/src/cpu.h new file mode 100644 index 0000000..c434ca8 --- /dev/null +++ b/src/cpu.h @@ -0,0 +1,6 @@ +#pragma once +#include +#include + +bool getcore(uint32_t); // gets the state of core (id) +void setcore(uint32_t, bool); // sets the state of core (id) diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..ef9881b --- /dev/null +++ b/src/error.c @@ -0,0 +1,18 @@ +#include "error.h" + +#include +#include +#include +#include +#include + +noreturn void fatal(char const* fmt, ...) { + char buf[128]; + va_list args; + va_start(args, fmt); + vsnprintf(buf, 128, fmt, args); + va_end(args); + + fprintf(stderr, "\033[91mE: %s\033[0m\n", buf); + exit(1); +} diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..e3d2a56 --- /dev/null +++ b/src/error.h @@ -0,0 +1,7 @@ +#pragma once +#include +#include +#include + +// prints an error message and aborts execution +noreturn void fatal(char const*, ...); diff --git a/src/main.c b/src/main.c index 7c01c7f..b352667 100644 --- a/src/main.c +++ b/src/main.c @@ -1,99 +1,12 @@ -#include #include #include #include -#include -#include #include #include #include -enum opt { - OPT_LIST_CORES = 1, // option that lists the total amount of cores that are set - OPT_SET_ALL = 2, // option to set all cores, regardless of their assumed state - OPT_VERBOSE = 4, // print which cores are disabled/enabled - OPT_INVERT = 8, // 'num' now represents the amount of cores to disable -}; - -char const* const cpu_path = "/sys/devices/system/cpu/cpu%i/online"; - -noreturn void fatal(char const* fmt, ...) { - char buf[128]; - va_list args; - va_start(args, fmt); - vsnprintf(buf, 128, fmt, args); - va_end(args); - - fprintf(stderr, "\033[91mE: %s\033[0m\n", buf); - exit(1); -} - -uint8_t getoptions(int32_t argc, char* const* argv, int32_t* ncpus) { - uint8_t opts = 0; - char opt; - - char const* const msg = "-%c has already been set"; - while ((opt = getopt(argc, argv, "lavi")) != -1) { - switch (opt) { - case 'l': - if (opts & OPT_LIST_CORES) fatal(msg, 'l'); - opts |= OPT_LIST_CORES; - break; - case 'a': - if (opts & OPT_SET_ALL) fatal(msg, 'a'); - opts |= OPT_SET_ALL; - break; - case 'v': - if (opts & OPT_VERBOSE) fatal(msg, 'v'); - opts |= OPT_VERBOSE; - break; - case 'i': - if (opts & OPT_INVERT) fatal(msg, 'i'); - opts |= OPT_INVERT; - break; - case '?': - fatal("usage: %s [number] [-l] [-a] [-v] [-i]", argv[0]); - } - } - - if (optind < argc) { - char* num = argv[optind]; - *ncpus = atoi(num); - } else fatal("you must provide a number!"); - - return opts; -} - -bool getcore(uint32_t id) { - // get the file path - char path[64]; // contains the file path (max length is 64 due to the path and a bunch of extra wiggle room) - snprintf(path, 64, cpu_path, id); // writes the path using the id - - // if the file doesn't exist; return true - if (access(path, R_OK) != 0) - return true; - - // read a character from the file, store in state - char state = '\0'; - FILE* f = fopen(path, "r"); - fread(&state, 1, 1, f); - fclose(f); - - // return whether state is truthy - return !!state; -} - -void setcore(uint32_t id, bool state) { - char path[64]; - snprintf(path, 64, cpu_path, id); - - char s = 0x30 + (char)state; // convert the state to a character - - // write the state to the file (creates file if it doesn't exist) - FILE* f = fopen(path, "w"); - fwrite(&s, 1, 1, f); - fclose(f); -} +#include "error.h" +#include "opts.h" int32_t main(int32_t argc, char** argv) { if (geteuid() != 0) fatal("must be executed as the root user!"); diff --git a/src/opts.c b/src/opts.c new file mode 100644 index 0000000..52787a2 --- /dev/null +++ b/src/opts.c @@ -0,0 +1,43 @@ +#include "opts.h" + +#include +#include +#include + +#include "error.h" + +uint8_t getoptions(int32_t argc, char* const* argv, int32_t* ncpus) { + uint8_t opts = 0; + char opt; + + char const* const msg = "-%c has already been set"; + while ((opt = getopt(argc, argv, "lavi")) != -1) { + switch (opt) { + case 'l': + if (opts & OPT_LIST_CORES) fatal(msg, 'l'); + opts |= OPT_LIST_CORES; + break; + case 'a': + if (opts & OPT_SET_ALL) fatal(msg, 'a'); + opts |= OPT_SET_ALL; + break; + case 'v': + if (opts & OPT_VERBOSE) fatal(msg, 'v'); + opts |= OPT_VERBOSE; + break; + case 'i': + if (opts & OPT_INVERT) fatal(msg, 'i'); + opts |= OPT_INVERT; + break; + case '?': + fatal("usage: %s [number] [-l] [-a] [-v] [-i]", argv[0]); + } + } + + if (optind < argc) { + char* num = argv[optind]; + *ncpus = atoi(num); + } else fatal("you must provide a number!"); + + return opts; +} diff --git a/src/opts.h b/src/opts.h new file mode 100644 index 0000000..9daf00a --- /dev/null +++ b/src/opts.h @@ -0,0 +1,11 @@ +#pragma once +#include + +enum opt { + OPT_LIST_CORES = 1, // option that lists the total amount of cores that are set + OPT_SET_ALL = 2, // option to set all cores, regardless of their assumed state + OPT_VERBOSE = 4, // print which cores are disabled/enabled + OPT_INVERT = 8, // 'num' now represents the amount of cores to disable +}; + +uint8_t getoptions(int32_t, char* const*, int32_t*);