/**
* unstickpixels – screen loop to try to unstick stuck pixels
*
* Copyright © 2013, 2015 Mattias Andrée (maandree@member.fsf.org)
*
* 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
#include
#include
#include
#include
#include
#include
#include
#define t(...) do { if (__VA_ARGS__) goto fail; } while (0)
#define WELCOME_MESSAGE \
"\033[?25l\033[H\033[2J" \
"\033[H\033[01;31mWARNING: Do not used this if you have epilepsia.\033[00m\n" \
"\n" \
"It is recommended to massage the defective dots, whilst\n" \
"running this program.\n" \
"\n" \
"Press C-c to quit, and Enter to start (C-c will quit).\n" \
"\n" \
"\n" \
"You should not have to run this program. If the manufacture or\n" \
"reseller of your monitor refuse to replace or repair the monitor\n" \
"that was broken, because of manufacturing error, when it was\n" \
"chiped to you, please consider yelling at the support, threaten\n" \
"to report the personally because of involvement in organised\n" \
"crime (not replacing hardware that was chipped broken when you\n" \
"selled it is a crime, and they do this in an organised fashion\n" \
"to make money), call their executive director persistently at\n" \
"inconvenient times, report them applicable board for consumer\n" \
"disputes/complaints or equivalent agency. If this program does\n" \
"not help, and the manufacture is Packard Bell, or its\n" \
"supersidiary Acer, tell them that you have tried a program\n" \
"that was prompted by the complete suckness and incapability\n" \
"to repair defects that they have agreed to repair. They suck!\n" \
"\n" \
"\n" \
"\n" \
"Copyright © 2013, 2015 Mattias Andrée (maandree@member.fsf.org)\n" \
"\n" \
"This program is free software: you can redistribute it and/or modify\n" \
"it under the terms of the GNU General Public License as published by\n" \
"the Free Software Foundation, either version 3 of the License, or\n" \
"(at your option) any later version.\n" \
"\n" \
"This program is distributed in the hope that it will be useful,\n" \
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \
"GNU General Public License for more details.\n" \
"\n" \
"You should have received a copy of the GNU General Public License\n" \
"along with this program. If not, see ."
/**
* The name of the process.
*/
const char* argv0;
/**
* Parse interval argument.
*
* @param argv The interval argument.
* @param interval Output parameter for the interval.
* @param nonzero With be set to zero if the interval is zero,
* otherwise it is set to a non-zero value (1).
* @return 0 on success, -1 on error.
*/
static int get_interval(const char* arg, struct timespec* interval, int* nonzero)
{
char* end;
*nonzero = 1;
t (!isdigit(*arg));
interval->tv_sec = (time_t)(errno = 0, strtol)(arg, &end, 10);
t (errno || *end);
interval->tv_nsec = interval->tv_sec % 1000;
interval->tv_sec /= 1000;
interval->tv_nsec *= 1000000L;
if (interval->tv_sec == 0)
if (interval->tv_nsec == 0)
*nonzero = 0;
return 0;
fail:
return -1;
}
/**
* Wrapper for fork(3) that clocks all signals in the parent.
*
* @return See fork(3).
*/
static pid_t xfork(void)
{
sigset_t set;
pid_t pid;
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, 0);
pid = fork();
if (pid != -1)
sigprocmask(SIG_UNBLOCK, &set, 0);
return pid;
}
int main(int argc, char* argv[])
{
int started = 0;
int with_sleep = 0;
struct timespec interval;
int _status;
pid_t pid;
argv0 = (argc ? "unstickpixels" : *argv);
if (argc > 1)
t (argv[1], &interval, &with_sleep);
printf(WELCOME_MESSAGE);
fflush(stdout);
if (read(STDIN_FILENO, &started, 1) < 0)
goto done;
started = 1;
pid = xfork();
if (pid == -1)
return perror(argv0), 1;
else if (pid)
goto parent;
t (printf("\033[H") == -1);
t (fflush(stdout));
for (;;)
{
t (printf("\033]P0FF0000\033[2J") == -1);
t (fflush(stdout));
if (with_sleep)
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
t (printf("\033]P000FF00\033[2J") == -1);
t (fflush(stdout));
if (with_sleep)
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
t (printf("\033]P00000FF\033[2J") == -1);
t (fflush(stdout));
if (with_sleep)
clock_nanosleep(CLOCK_MONOTONIC, 0, &interval, NULL);
}
fail:
return 0;
parent:
waitpid(pid, &_status, 0);
done:
printf("%s\033[?25h\033[H\033[2J", started ? "\033]P0000000" : "");
fflush(stdout);
return 0;
}