p.enes.lv is a Fediverse instance that uses the ActivityPub protocol. In other words, users at this host can communicate with people that use software like Mastodon, Pleroma, Friendica, etc. all around the world.
This server runs the snac software and there is no automatic sign-up process.
#define Monday 30
, they aren't scoped/namespaced to the enum itself. Like if you wrote struct { int a; int b; };
and now anything.b
always works. (Which is how ancient pre-standard C actually worked which is why you have fields in UNIX structures prefixed to make them unique, st_
for struct stat
, tv_
for struct timeval
, etc.)/* GnuPowerUtils ACPI S3 program
Copyright © 2025 DiffieHellman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include "shared.h"
int main(int argc, char *argv[])
{
/* print help or version of there are any arguments */
if (argc >= 2){help_or_version(argv[0], argv[1]);}
/* exit(1) if group does not exist or member is not in group */
check_group_membership();
/* change to root user */
if (setuid(0) != 0){error_exit("Suspend binary is not setuid.");}
/* open mem_sleep and state */
int mem_sleep = open("/sys/power/mem_sleep", O_WRONLY);
int state = open("/sys/power/state", O_WRONLY);
if (!mem_sleep || !state){perror_exit("Linux doesn't support Suspend-to-RAM");}
/* write deep to /sys/power/mem_sleep then mem to /sys/power/state to Suspend-to-RAM */
if (write(mem_sleep, "deep\n", 5) != 5){perror_exit("Writing deep failed");}
if (write(state, "mem\n", 4) != 4){perror_exit("Writing mem failed");}
/* close the fd's */
close(mem_sleep);
close(state);
return 0;
}
shared.h:
/* GnuPowerUtils shared functions
Copyright © 2025 DiffieHellman
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <grp.h>
/* definitions and functions that would otherwise be needlessly duplicated between files */
#ifndef GROUP_NAME
#define GROUP_NAME "gnupu"
#endif
#define VERSION "0"
void error_exit(char s[])
{
fprintf(stderr,"%s\n",s);
exit(1);
}
void perror_exit(char s[])
{
perror(s);
exit(1);
}
void check_group_membership()
{
/* get gid of power group and see if user is a member of that gid */
struct group *gnupu = getgrnam(GROUP_NAME);
if (!gnupu){error_exit(GROUP_NAME" group does not exist.\n");}
if (!group_member(gnupu->gr_gid)){error_exit("User is not in "GROUP_NAME" group.\n");}
}
void help_or_version(char z[], char s[])
{
/* no point bothering to use getopt or memcmp */
if (s[0] == '-' && ((s[1] == '-' && s[2] == 'v') || s[1] == 'v'))
{
printf("gnupu (GNU power utils) "VERSION"\n"\
"Copyright © 2025 DiffieHellman\n"\
"License AGPLv3+: GNU AGPL version 3 or later <https://www.gnu.org/licenses/agpl-3.0.html>.\n"\
"This is free software: you are free to change and redistribute it.\n"\
"There is NO WARRANTY, to the extent permitted by law.\n\n"\
"Written by DiffieHellman.\n");
}
else
{
printf("Usage: %s [OPTION]\n"\
"Do power operation on the system\n\n"\
"With no argument, do the operation, otherwise show help or version\n\n"\
"-h, --help show help and exit\n"\
"-v, --version output version information and exit\n\n"\
"Usage:\n"\
"%s Ensure user is in the "GROUP_NAME" group and execute without arguments.\n\n"\
"Documentation: `info gnupu`\n", z, z);
}
exit(0);
}
silly little thing i made to debug that heisenbug
collecting all the things that i want to log and printing them after the fact, this avoids the overhead of printing immediately that seeming skewed the timing enough to make the bug disappear
there is one logger for every relevant thread, because synchronizing the logging would have also skewed the result obviously
struct microlog_entry
{
LONGLONG perf;
const char *text;
};
#define MICROLOGGER_CAP 100
struct micrologger
{
size_t pos;
size_t read_pos;
struct microlog_entry entries[MICROLOGGER_CAP];
};
#define microlog(l, text) if (l.pos < MICROLOGGER_CAP) { \
LARGE_INTEGER perf; \
QueryPerformanceCounter(&perf); \
l.entries[l.pos++] = (struct microlog_entry) { perf.QuadPart, text }; \
}
static struct micrologger l_grabber_events;
static struct micrologger l_grabber_samples;
static struct micrologger l_main;
void microlog_flush()
{
#define NUM_MICROLOGGERS 3
struct micrologger *loggers[NUM_MICROLOGGERS] = { &l_grabber_events, &l_grabber_samples, &l_main };
for (;;) {
struct micrologger *least = NULL;
for (size_t i = 0; i < NUM_MICROLOGGERS; i++) {
if (loggers[i]->read_pos == loggers[i]->pos)
continue;
if (!least || loggers[i]->entries[loggers[i]->read_pos].perf < least->entries[least->read_pos].perf)
least = loggers[i];
}
if (!least)
break;
printf("%s\n", least->entries[least->read_pos].text);
least->read_pos++;
}
#undef NUM_MICROLOGGERS
}