From b037ed3e441ffbb5957007eb1a886cf23f54694a Mon Sep 17 00:00:00 2001 From: Juan RP Date: Wed, 11 Jun 2014 12:26:35 +0200 Subject: New suspend(8) utility that is able to suspend to ram/disk. --- Makefile | 4 +- suspend.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 suspend.c diff --git a/Makefile b/Makefile index 5638b3f..f4e15f7 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,13 @@ SCRIPTS= 1 2 3 ctrlaltdel all: $(CC) $(CFLAGS) halt.c -o halt $(CC) $(CFLAGS) pause.c -o pause + $(CC) $(CFLAGS) suspend.c -o suspend install: install -d ${DESTDIR}/${PREFIX}/bin install -m755 halt ${DESTDIR}/${PREFIX}/bin install -m755 pause ${DESTDIR}/${PREFIX}/bin + install -m755 suspend ${DESTDIR}/${PREFIX}/bin install -m755 shutdown.sh ${DESTDIR}/${PREFIX}/bin/shutdown ln -s halt ${DESTDIR}/${PREFIX}/bin/poweroff ln -s halt ${DESTDIR}/${PREFIX}/bin/reboot @@ -24,4 +26,4 @@ install: cp -aP services/* ${DESTDIR}/etc/sv/ clean: - -rm -f halt pause + -rm -f halt pause suspend diff --git a/suspend.c b/suspend.c new file mode 100644 index 0000000..7522578 --- /dev/null +++ b/suspend.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2014 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#define SYS_STATE "/sys/power/state" +#define SYS_DISK "/sys/power/disk" + +#define MODE_RAM 0x1 +#define MODE_DISK 0x2 + +static void +usage(bool fail) +{ + fprintf(stdout, + "Usage: suspend [OPTIONS]\n\n" + "OPTIONS\n" + " -s --show Show supported modes\n" + " -h --help Show usage\n" + " -H --hibernate Hibernate rather than suspend-to-ram\n\n"); + exit(fail ? EXIT_FAILURE : EXIT_SUCCESS); +} + +static int +getmodes(void) +{ + FILE *f; + char v[LINE_MAX]; + int mode = 0; + + if ((f = fopen(SYS_STATE, "r"))) { + fgets(v, sizeof(v), f); + fclose(f); + if (strstr(v, "mem")) + mode |= MODE_RAM; + if (strstr(v, "disk")) + mode |= MODE_DISK; + } + return mode; +} + +static void +writemode(int mode) +{ + FILE *f; + + if ((f = fopen("/sys/power/state", "w")) == NULL) { + perror("cannot open /sys/power/state"); + exit(EXIT_FAILURE); + } + if (mode & MODE_RAM) { + fputs("mem", f); + } else { + fputs("disk", f); + } + fclose(f); +} + +int +main(int argc, char **argv) +{ + const char *shortopts = "shH"; + const struct option longopts[] = { + { "show", no_argument, NULL, 's' }, + { "help", no_argument, NULL, 'h' }, + { "hibernate", no_argument, NULL, 'H' }, + { NULL, 0, NULL, 0 } + }; + int c, modes = 0; + bool show = false, hibernate = false; + + while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { + switch (c) { + case 's': + show = true; + break; + case 'h': + usage(false); + /* NOTREACHED */ + case 'H': + hibernate = true; + break; + case '?': + default: + usage(true); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (show) { + modes = getmodes(); + if (modes & MODE_RAM) + printf("suspend-to-ram "); + if (modes & MODE_DISK) + printf("suspend-to-disk "); + + printf("\n"); + } else if (hibernate) { + writemode(MODE_DISK); + } else { + writemode(MODE_RAM); + } + + exit(EXIT_SUCCESS); +} -- cgit 1.4.1