mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-28 11:43:01 +02:00
149 lines
2.8 KiB
C
149 lines
2.8 KiB
C
#include <err.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#define RESETME "/mnt/cfg/infix/.reset"
|
|
#define touch(f) mknod((f), S_IFREG|0644, 0)
|
|
|
|
int rawgetch(void)
|
|
{
|
|
struct termios saved, c;
|
|
int key;
|
|
|
|
if (tcgetattr(fileno(stdin), &saved) < 0)
|
|
return -1;
|
|
|
|
c = saved;
|
|
c.c_lflag &= ~ICANON;
|
|
c.c_lflag &= ~ECHO;
|
|
c.c_cc[VMIN] = 1;
|
|
c.c_cc[VTIME] = 0;
|
|
|
|
if (tcsetattr(fileno(stdin), TCSANOW, &c) < 0) {
|
|
tcsetattr(fileno(stdin), TCSANOW, &saved);
|
|
return -1;
|
|
}
|
|
|
|
key = getchar();
|
|
tcsetattr(fileno(stdin), TCSANOW, &saved);
|
|
|
|
return key;
|
|
}
|
|
|
|
int yorn(const char *prompt)
|
|
{
|
|
char yorn;
|
|
|
|
fputs(prompt, stderr);
|
|
|
|
yorn = rawgetch();
|
|
fprintf(stderr, "%c\n", yorn);
|
|
if (yorn != 'y' && yorn != 'Y')
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int usage(int rc)
|
|
{
|
|
printf("usage: factory [opts]\n"
|
|
"\n"
|
|
"Options:\n"
|
|
" -h, --help This help text\n"
|
|
" -r, --no-reboot Don't reboot. Reboot manually to activate.\n"
|
|
" -y, --assume-yes Automatic yes to prompts; assume \"yes\" as answer to all\n"
|
|
" prompts and run non-interactively\n"
|
|
"\n"
|
|
"Note: this program initiates a factory reset by raising a flag and rebooting\n"
|
|
" the system. When it comes back up it safely removes all the OverlayFS\n"
|
|
" worker/upper directories for /etc, /home, and /var\n");
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int run(const char *cmd)
|
|
{
|
|
int status = system(cmd);
|
|
int rc;
|
|
|
|
rc = WEXITSTATUS(status);
|
|
|
|
if (WIFEXITED(status))
|
|
return rc;
|
|
|
|
if (WIFSIGNALED(status)) {
|
|
if (rc == 0)
|
|
rc = 1; /* adjust, we were aborted */
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct option long_opts[] = {
|
|
{ "help", 0, NULL, 'h' },
|
|
{ "no-reboot", 0, NULL, 'r' },
|
|
{ "assume-yes", 0, NULL, 'y' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
int reboot = 1;
|
|
int yes = 0;
|
|
char *tty;
|
|
int c;
|
|
|
|
while ((c = getopt_long(argc, argv, "h?ry", long_opts, NULL)) != EOF) {
|
|
switch (c) {
|
|
case 'h':
|
|
case '?':
|
|
return usage(0);
|
|
|
|
case 'r':
|
|
reboot = 0;
|
|
break;
|
|
|
|
case 'y':
|
|
yes = 1;
|
|
break;
|
|
|
|
default:
|
|
return usage(1);
|
|
}
|
|
}
|
|
|
|
tty = ttyname(STDIN_FILENO);
|
|
if (!tty && errno == ENOTTY)
|
|
yes = 1;
|
|
|
|
if (argv[0][0] == '-' && tty && strcmp(tty, "/dev/console"))
|
|
errx(1, "factory reset only allowed from console login!");
|
|
|
|
if (yes || yorn("Factory reset device (y/N)? ")) {
|
|
if (touch(RESETME) && errno != EEXIST)
|
|
err(1, "failed");
|
|
|
|
warnx("scheduled factory reset on next boot.");
|
|
if (reboot && (yes || yorn("Reboot now to perform reset, (y/N)? ")))
|
|
return run("/sbin/reboot");
|
|
|
|
warnx("remember to reboot the system to perform the factory reset.");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Local Variables:
|
|
* indent-tabs-mode: t
|
|
* c-file-style: "linux"
|
|
* End:
|
|
*/
|