/* * PM service for other drivers. */ int pm_set_power(int state) { int error; switch (state) { case PWR_ON: error = pm_resume(); break; case PWR_SUSPEND: error = pm_suspend(); break; case PWR_OFF: error = pm_poweroff(); break; case PWR_REBOOT: error = pm_reboot(); break; default: error = EINVAL; } return error; }
/* * PM event notification. */ void pm_notify(int event) { struct pm_softc *sc = pm_softc; int s; if (event == PME_USER_ACTIVITY) { /* * Reload suspend timer for user activity. */ s = splhigh(); sc->idlecnt = 0; splx(s); if (!sc->lcd_on) pm_lcd_on(); return; } DPRINTF(("pm: notify %d\n", event)); if (sc->powtask != TASK_NULL) { /* * Power server exists. */ switch (event) { case PME_PWRBTN_PRESS: case PME_SLPBTN_PRESS: case PME_LOW_BATTERY: case PME_LCD_CLOSE: /* * Post an exception to the power server. * Then, the power server will query PM event. */ sc->lastevt = event; DPRINTF(("pm: post %d\n", event)); exception_post(sc->powtask, SIGPWR); break; case PME_LCD_OPEN: sc->lastevt = PME_NO_EVENT; pm_lcd_on(); break; } } else { /* * No power server. * Map power event to default action. */ switch (event) { case PME_PWRBTN_PRESS: pm_poweroff(); break; case PME_SLPBTN_PRESS: case PME_LOW_BATTERY: pm_suspend(); break; case PME_LCD_OPEN: pm_lcd_on(); break; case PME_LCD_CLOSE: pm_lcd_off(); break; } } }
int main(int argc, char **argv) { int c; char display_name[MAXNAMELEN + 9] = "DISPLAY="; char xauthority[MAXPATHLEN + 12] = "XAUTHORITY="; struct passwd *pw; (void) signal(SIGHUP, SIG_IGN); (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); (void) signal(SIGTSTP, SIG_IGN); (void) signal(SIGTTIN, SIG_IGN); (void) signal(SIGTTOU, SIG_IGN); /* * If suspend is invoked from a daemon (case 1 above), it * will not have a working stdin, stdout and stderr. We need * these to print proper error messages and possibly get user * input. We attach them to console and hope that attachment * works. */ if (ttyname(0) == NULL) { no_tty = 1; (void) dup2(open("/dev/console", O_RDONLY), 0); (void) dup2(open("/dev/console", O_WRONLY), 1); (void) dup2(open("/dev/console", O_WRONLY), 2); } while ((c = getopt(argc, argv, "fnxhtd:")) != EOF) { switch (c) { case 'f': /* * Force machine to poweroff if * suspend fails */ flags |= FORCE; break; case 'n': /* No warning popups - Obsolete */ flags |= NO_WARN; break; case 'x': /* Don't try to screenlock */ flags |= NO_XLOCK; break; case 'h': /* Do a shutdown instead of suspend */ flags |= SHUTDOWN; break; case 'd': /* Needswork */ /* Set the DISPLAY value in the environment */ if (strlen(optarg) >= MAXNAMELEN) { (void) printf(gettext("Error: " "display name is too long.\n")); return (1); } (void) strcat(display_name, optarg); if (putenv(display_name) != 0) { (void) printf(gettext("Error: " "unable to set DISPLAY " "environment variable.\n")); return (1); } break; case 't': /* Test, don't actually do any operation */ flags |= TEST; break; default: (void) printf(gettext("USAGE: suspend " "[-fnxh] [-d <display>]\n")); return (1); } } /* * The action of pressing power key and power button on a MOU-3 machine * causes suspend being invoked with SYSSUSPENDDODEFAULT * enviromental variable set - indicating the default action is machine * dependent: for MOU-3 type machine, "LowPower" mode is the default, * for all the rest, "Suspend" is the default. Existing suspend * flags works the same. */ if (getenv("SYSSUSPENDDODEFAULT")) if (is_mou3()) flags |= LOWPOWER; if ((flags & FORCE) && (flags & LOWPOWER)) flags &= ~LOWPOWER; /* * Flag "-h" overrides flag "-f". */ if ((flags & SHUTDOWN) && (flags & FORCE)) flags &= ~(FORCE | LOWPOWER); if (flags & FORCE) flags |= NO_WARN; /* * Check initally if the user has the authorizations to * do either a suspend or shutdown. pm_suspend() will also * make this test, so we could defer till then, but if we * do it now, we at least prevent a lot of unneeded setup. */ pw = getpwuid(getuid()); (void) strncpy(user, pw->pw_name, NMAX); if ((flags & (FORCE|SHUTDOWN)) && (chkauthattr(AUTHNAME_SHUTDOWN, pw->pw_name) != 1)) { (void) printf(gettext("User does not have correct " "authorizations to shutdown the machine.\n")); exit(1); } if (!(flags & SHUTDOWN) && (chkauthattr(AUTHNAME_SUSPEND, pw->pw_name) != 1)) { (void) printf(gettext("User does not have correct " "authorizations to suspend.\n")); exit(1); } /* * If we are only shutting down, there isn't much to do, just * call pm_poweroff(), and let it do all the work. */ if (flags & SHUTDOWN) { /* * pm_poweroff either powers off or exits, * so there is no return. */ if (flags & TEST) { (void) printf("TEST: This machine would have " "powered off\n"); exit(1); } else { pm_poweroff(); } /* NOTREACHED */ } /* * If XAUTHORITY environment variable is not set, try to set * one up. */ if (getenv("XAUTHORITY") == NULL) (void) putenv(get_xauthority(xauthority)); /* * In case of "suspend" being called from daemon "powerd", * signal SIGALRM is blocked so use "sigset()" instead of "signal()". */ (void) sigset(SIGALRM, alarm_handler); /* Call the "suspend" function to do the last of the work */ pm_suspend(); if (refresh_dt() == -1) { (void) printf("%s: Failed to refresh screen.\n", argv[0]); return (1); } return (0); }
/* * This entry point _should_ be the common entry to suspend. It is in * it's entirety here, but would be best moved to libpower when that * is available. */ static void pm_suspend(void) { int cprarg = AD_SUSPEND; enum adt_uadmin_fcn fcn_id = ADT_FCN; au_event_t event_id = ADT_uadmin_freeze; adt_event_data_t *event = NULL; /* event to be generated */ adt_session_data_t *ah = NULL; /* audit session handle */ /* * Does the user have permission to use this command? */ if (chkauthattr(AUTHNAME_SUSPEND, user) != 1) { (void) printf(gettext("User %s does not have correct " "authorizations to suspend this machine.\n"), user); exit(1); } if (flags & LOWPOWER) { if (bringto_lowpower() == -1) { (void) printf(gettext("LowPower Failed\n")); exit(1); } } else if (flags & TEST) { /* * Test mode, do checks as if a real suspend, but * don't actually do the suspend. */ /* Check if suspend is supported */ if (pm_check_suspend() == -1) { suspend_error(errno); } (void) printf(gettext("TEST: Suspend would have been" " performed\n")); } else { /* Check if suspend is supported */ if (pm_check_suspend() == -1) { suspend_error(errno); } /* * We are about to suspend this machine, try and * lock the screen. We don't really care if this * succeeds or not, but that we actually tried. We * also know that we have sufficient privileges to * be here, so we lock the screen now, even if * suspend actually fails. * Note that garbage is sometimes displayed, and * we don't really care about it, so we toss all * text response. * it would also be good if there were another option * instead of launcing a file, as the disk might be * spun down if we are suspending due to idle. */ if (!(flags & NO_XLOCK)) { (void) system("/usr/bin/xdg-screensaver lock " " >/dev/null 2>&1"); } /* Time to do the actual deed! */ /* * Before we actually suspend, we need to audit and * "suspend" the audit files. */ /* set up audit session and event */ if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) == 0) { if ((event = adt_alloc_event(ah, event_id)) != NULL) { event->adt_uadmin_freeze.fcn = fcn_id; event->adt_uadmin_freeze.mdep = NULL; if (adt_put_event(event, ADT_SUCCESS, 0) != 0) { (void) fprintf(stderr, gettext( "%s: can't put audit event\n"), argvl[0]); } else { wait_for_auqueue(); } } (void) change_audit_file(); } else { (void) fprintf(stderr, gettext( "%s: can't start audit session\n"), argvl[0]); } if (uadmin(A_FREEZE, cprarg, 0) != 0) { (void) printf(gettext("Suspend Failed\n")); if (flags & FORCE) { /* * Note, that if we actually poweroff, * that the poweroff function will handle * that audit trail, and the resume * trail is effectively done. */ pm_poweroff(); } else { /* suspend_error() will exit. */ suspend_error(errno); /* * Audit the suspend failure and * reuse the event, but don't create one * if we don't already have one. */ if (event != NULL) { (void) adt_put_event(event, ADT_FAILURE, 0); } } } /* * Write the thaw event. */ if (ah != NULL) { if ((event == NULL) && ((event = adt_alloc_event(ah, ADT_uadmin_thaw)) == NULL)) { (void) fprintf(stderr, gettext( "%s: can't allocate thaw audit event\n"), argvl[0]); } else { event->adt_uadmin_thaw.fcn = fcn_id; if (adt_put_event(event, ADT_SUCCESS, 0) != 0) { (void) fprintf(stderr, gettext( "%s: can't put thaw audit event\n"), argvl[0]); } (void) adt_free_event(event); } } } if ((no_tty ? 0 : 1) && !(flags & NO_XLOCK)) { pm_do_auth(ah); } (void) adt_end_session(ah); }