1623ec8b0SRandy Fishel /* 2623ec8b0SRandy Fishel * CDDL HEADER START 3623ec8b0SRandy Fishel * 4623ec8b0SRandy Fishel * The contents of this file are subject to the terms of the 5623ec8b0SRandy Fishel * Common Development and Distribution License (the "License"). 6623ec8b0SRandy Fishel * You may not use this file except in compliance with the License. 7623ec8b0SRandy Fishel * 8623ec8b0SRandy Fishel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9623ec8b0SRandy Fishel * or http://www.opensolaris.org/os/licensing. 10623ec8b0SRandy Fishel * See the License for the specific language governing permissions 11623ec8b0SRandy Fishel * and limitations under the License. 12623ec8b0SRandy Fishel * 13623ec8b0SRandy Fishel * When distributing Covered Code, include this CDDL HEADER in each 14623ec8b0SRandy Fishel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15623ec8b0SRandy Fishel * If applicable, add the following below this CDDL HEADER, with the 16623ec8b0SRandy Fishel * fields enclosed by brackets "[]" replaced with your own identifying 17623ec8b0SRandy Fishel * information: Portions Copyright [yyyy] [name of copyright owner] 18623ec8b0SRandy Fishel * 19623ec8b0SRandy Fishel * CDDL HEADER END 20623ec8b0SRandy Fishel */ 21623ec8b0SRandy Fishel /* 22623ec8b0SRandy Fishel * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23623ec8b0SRandy Fishel * Use is subject to license terms. 2433f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 25623ec8b0SRandy Fishel */ 26623ec8b0SRandy Fishel 27623ec8b0SRandy Fishel /* 28623ec8b0SRandy Fishel * This code has a lot in common with the original sys-suspend 29623ec8b0SRandy Fishel * code. Windowing facilities have been removed, and it has been 30623ec8b0SRandy Fishel * updated to use more recent API's. 31623ec8b0SRandy Fishel */ 32623ec8b0SRandy Fishel #include <stdio.h> 33623ec8b0SRandy Fishel #include <fcntl.h> 34623ec8b0SRandy Fishel #include <stdlib.h> 35623ec8b0SRandy Fishel #include <string.h> 36623ec8b0SRandy Fishel #include <strings.h> 37623ec8b0SRandy Fishel #include <unistd.h> 38623ec8b0SRandy Fishel #include <libintl.h> 39623ec8b0SRandy Fishel #include <locale.h> 40623ec8b0SRandy Fishel #include <utility.h> 41623ec8b0SRandy Fishel #include <signal.h> 42623ec8b0SRandy Fishel #include <errno.h> 43623ec8b0SRandy Fishel #include <setjmp.h> 44623ec8b0SRandy Fishel #include <pwd.h> 45623ec8b0SRandy Fishel #include <syslog.h> 46623ec8b0SRandy Fishel #include <sys/types.h> 47623ec8b0SRandy Fishel #include <sys/param.h> 48623ec8b0SRandy Fishel #include <sys/utsname.h> 49623ec8b0SRandy Fishel #include <sys/uadmin.h> 50623ec8b0SRandy Fishel #include <auth_attr.h> 51623ec8b0SRandy Fishel #include <auth_list.h> 52623ec8b0SRandy Fishel #include <secdb.h> 53623ec8b0SRandy Fishel #include <security/pam_appl.h> 54623ec8b0SRandy Fishel #include <utmpx.h> 55623ec8b0SRandy Fishel 56623ec8b0SRandy Fishel /* For audit */ 57623ec8b0SRandy Fishel #include <bsm/adt.h> 58623ec8b0SRandy Fishel #include <bsm/adt_event.h> 59623ec8b0SRandy Fishel 60623ec8b0SRandy Fishel #include <sys/wait.h> 61623ec8b0SRandy Fishel #include <sys/stat.h> 62623ec8b0SRandy Fishel #include <sys/pm.h> 63623ec8b0SRandy Fishel #include <dirent.h> 64623ec8b0SRandy Fishel #include <sys/cpr.h> 65623ec8b0SRandy Fishel 66623ec8b0SRandy Fishel /* STATICUSED */ 67623ec8b0SRandy Fishel struct utmpx utmp; 68623ec8b0SRandy Fishel #define NMAX (sizeof (utmp.ut_name)) 69623ec8b0SRandy Fishel 70623ec8b0SRandy Fishel /* 71623ec8b0SRandy Fishel * Authorizations used by Power Management 72623ec8b0SRandy Fishel */ 73623ec8b0SRandy Fishel #define AUTHNAME_SHUTDOWN "solaris.system.shutdown" 74623ec8b0SRandy Fishel #define AUTHNAME_SUSPEND_RAM "solaris.system.power.suspend.ram" 75623ec8b0SRandy Fishel #define AUTHNAME_SUSPEND_DISK "solaris.system.power.suspend.disk" 76623ec8b0SRandy Fishel 77623ec8b0SRandy Fishel /* Platform specific definitions */ 78623ec8b0SRandy Fishel #ifdef i386 79623ec8b0SRandy Fishel #define AD_CHECK_SUSPEND AD_CHECK_SUSPEND_TO_RAM 80623ec8b0SRandy Fishel #define AD_SUSPEND AD_SUSPEND_TO_RAM 81623ec8b0SRandy Fishel #define ADT_FCN ADT_UADMIN_FCN_AD_SUSPEND_TO_RAM 82623ec8b0SRandy Fishel #define AUTHNAME_SUSPEND AUTHNAME_SUSPEND_RAM 83623ec8b0SRandy Fishel #else 84623ec8b0SRandy Fishel #define AD_CHECK_SUSPEND AD_CHECK_SUSPEND_TO_DISK 85623ec8b0SRandy Fishel #define AD_SUSPEND AD_SUSPEND_TO_DISK 86623ec8b0SRandy Fishel #define ADT_FCN ADT_UADMIN_FCN_AD_SUSPEND_TO_DISK 87623ec8b0SRandy Fishel #define AUTHNAME_SUSPEND AUTHNAME_SUSPEND_DISK 88623ec8b0SRandy Fishel #endif 89623ec8b0SRandy Fishel 90623ec8b0SRandy Fishel static int flags = 0; 91623ec8b0SRandy Fishel static int no_tty = 0; 92623ec8b0SRandy Fishel /* 93623ec8b0SRandy Fishel * Flag definitions - could go in a header file, but there are just a few 94623ec8b0SRandy Fishel */ 95623ec8b0SRandy Fishel #define FORCE 0x001 96623ec8b0SRandy Fishel #define NO_WARN 0x002 97623ec8b0SRandy Fishel #define NO_XLOCK 0x004 98623ec8b0SRandy Fishel #define SHUTDOWN 0x008 99623ec8b0SRandy Fishel #define LOWPOWER 0x010 100623ec8b0SRandy Fishel #define TEST 0x800 101623ec8b0SRandy Fishel 102623ec8b0SRandy Fishel static sigjmp_buf jmp_stack; 103623ec8b0SRandy Fishel static char user[NMAX + 1]; 104623ec8b0SRandy Fishel static char **argvl; 105623ec8b0SRandy Fishel 106623ec8b0SRandy Fishel 107623ec8b0SRandy Fishel 108623ec8b0SRandy Fishel /* 109623ec8b0SRandy Fishel * Forward Declarations. 110623ec8b0SRandy Fishel */ 111623ec8b0SRandy Fishel static void pm_poweroff(void); 112623ec8b0SRandy Fishel static int bringto_lowpower(void); 113623ec8b0SRandy Fishel static int is_mou3(void); 114623ec8b0SRandy Fishel static void suspend_error(int); 115623ec8b0SRandy Fishel static int pm_check_suspend(void); 116623ec8b0SRandy Fishel static void pm_suspend(void); 117623ec8b0SRandy Fishel static void pm_do_auth(adt_session_data_t *); 118623ec8b0SRandy Fishel 119623ec8b0SRandy Fishel /* 120623ec8b0SRandy Fishel * External Declarations. 121623ec8b0SRandy Fishel */ 122623ec8b0SRandy Fishel extern int pam_tty_conv(int, struct pam_message **, 123623ec8b0SRandy Fishel struct pam_response **, void *); 124623ec8b0SRandy Fishel extern char *optarg; 125623ec8b0SRandy Fishel 126623ec8b0SRandy Fishel /* 127623ec8b0SRandy Fishel * Audit related code. I would also think that some of this could be 128623ec8b0SRandy Fishel * in external code, as they could be useful of other apps. 129623ec8b0SRandy Fishel */ 130623ec8b0SRandy Fishel /* 131623ec8b0SRandy Fishel * Write audit event. Could be useful in the PM library, so it is 132623ec8b0SRandy Fishel * included here. For the most part it is only used by the PAM code. 133623ec8b0SRandy Fishel */ 134623ec8b0SRandy Fishel static void 135623ec8b0SRandy Fishel pm_audit_event(adt_session_data_t *ah, au_event_t event_id, int status) 136623ec8b0SRandy Fishel { 137623ec8b0SRandy Fishel adt_event_data_t *event; 138623ec8b0SRandy Fishel 139623ec8b0SRandy Fishel 140623ec8b0SRandy Fishel if ((event = adt_alloc_event(ah, event_id)) == NULL) { 141623ec8b0SRandy Fishel return; 142623ec8b0SRandy Fishel } 143623ec8b0SRandy Fishel 144623ec8b0SRandy Fishel (void) adt_put_event(event, 145623ec8b0SRandy Fishel status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAILURE, 146623ec8b0SRandy Fishel status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM + status); 147623ec8b0SRandy Fishel 148623ec8b0SRandy Fishel adt_free_event(event); 149623ec8b0SRandy Fishel } 150623ec8b0SRandy Fishel 151623ec8b0SRandy Fishel #define RETRY_COUNT 15 152623ec8b0SRandy Fishel static int 153623ec8b0SRandy Fishel change_audit_file(void) 154623ec8b0SRandy Fishel { 155623ec8b0SRandy Fishel pid_t pid; 156623ec8b0SRandy Fishel 157623ec8b0SRandy Fishel if (!adt_audit_state(AUC_AUDITING)) { 158623ec8b0SRandy Fishel /* auditd not running, just return */ 159623ec8b0SRandy Fishel return (0); 160623ec8b0SRandy Fishel } 161623ec8b0SRandy Fishel 162623ec8b0SRandy Fishel if ((pid = fork()) == 0) { 163623ec8b0SRandy Fishel (void) execl("/usr/sbin/audit", "audit", "-n", NULL); 164623ec8b0SRandy Fishel (void) fprintf(stderr, gettext("error changing audit files: " 165623ec8b0SRandy Fishel "%s\n"), strerror(errno)); 166623ec8b0SRandy Fishel _exit(-1); 167623ec8b0SRandy Fishel } else if (pid == -1) { 168623ec8b0SRandy Fishel (void) fprintf(stderr, gettext("error changing audit files: " 169623ec8b0SRandy Fishel "%s\n"), strerror(errno)); 170623ec8b0SRandy Fishel return (-1); 171623ec8b0SRandy Fishel } else { 172623ec8b0SRandy Fishel pid_t rc; 173623ec8b0SRandy Fishel int retries = RETRY_COUNT; 174623ec8b0SRandy Fishel 175623ec8b0SRandy Fishel /* 176623ec8b0SRandy Fishel * Wait for audit(1M) -n process to complete 177623ec8b0SRandy Fishel * 178623ec8b0SRandy Fishel */ 179623ec8b0SRandy Fishel do { 180623ec8b0SRandy Fishel if ((rc = waitpid(pid, NULL, WNOHANG)) == pid) { 181623ec8b0SRandy Fishel return (0); 182623ec8b0SRandy Fishel } else if (rc == -1) { 183623ec8b0SRandy Fishel return (-1); 184623ec8b0SRandy Fishel } else { 185623ec8b0SRandy Fishel (void) sleep(1); 186623ec8b0SRandy Fishel retries--; 187623ec8b0SRandy Fishel } 188623ec8b0SRandy Fishel 189623ec8b0SRandy Fishel } while (retries != 0); 190623ec8b0SRandy Fishel } 191623ec8b0SRandy Fishel return (-1); 192623ec8b0SRandy Fishel } 193623ec8b0SRandy Fishel 194623ec8b0SRandy Fishel static void 195623ec8b0SRandy Fishel wait_for_auqueue() 196623ec8b0SRandy Fishel { 197623ec8b0SRandy Fishel au_stat_t au_stat; 198623ec8b0SRandy Fishel int retries = 10; 199623ec8b0SRandy Fishel 200623ec8b0SRandy Fishel while (retries-- && auditon(A_GETSTAT, (caddr_t)&au_stat, NULL) == 0) { 201623ec8b0SRandy Fishel if (au_stat.as_enqueue == au_stat.as_written) { 202623ec8b0SRandy Fishel break; 203623ec8b0SRandy Fishel } 204623ec8b0SRandy Fishel (void) sleep(1); 205623ec8b0SRandy Fishel } 206623ec8b0SRandy Fishel } 207623ec8b0SRandy Fishel 208623ec8b0SRandy Fishel /* End of Audit-related code */ 209623ec8b0SRandy Fishel 210623ec8b0SRandy Fishel /* ARGSUSED0 */ 211623ec8b0SRandy Fishel static void 212623ec8b0SRandy Fishel alarm_handler(int sig) 213623ec8b0SRandy Fishel { 214623ec8b0SRandy Fishel siglongjmp(jmp_stack, 1); 215623ec8b0SRandy Fishel } 216623ec8b0SRandy Fishel 217623ec8b0SRandy Fishel /* 218623ec8b0SRandy Fishel * These are functions that would be candidates for moving to a library. 219623ec8b0SRandy Fishel */ 220623ec8b0SRandy Fishel 221623ec8b0SRandy Fishel /* 222623ec8b0SRandy Fishel * pm_poweroff - similar to poweroff(1M) 223623ec8b0SRandy Fishel * This should do the same auditing as poweroff(1m) would do when it 224623ec8b0SRandy Fishel * becomes a libpower function. Till then we use poweroff(1m). 225623ec8b0SRandy Fishel */ 226623ec8b0SRandy Fishel static void 227623ec8b0SRandy Fishel pm_poweroff(void) 228623ec8b0SRandy Fishel { 229623ec8b0SRandy Fishel if (chkauthattr(AUTHNAME_SHUTDOWN, user) != 1) { 230623ec8b0SRandy Fishel (void) printf(gettext("User %s does not have correct " 231623ec8b0SRandy Fishel "authorizations to shutdown this machine.\n"), user); 232623ec8b0SRandy Fishel exit(1); 233623ec8b0SRandy Fishel } 234623ec8b0SRandy Fishel openlog("suspend", 0, LOG_DAEMON); 235623ec8b0SRandy Fishel syslog(LOG_NOTICE, "System is being shut down."); 236623ec8b0SRandy Fishel closelog(); 237623ec8b0SRandy Fishel 238623ec8b0SRandy Fishel /* 239623ec8b0SRandy Fishel * Call poweroff(1m) to shut down the system. 240623ec8b0SRandy Fishel */ 241623ec8b0SRandy Fishel (void) execl("/usr/sbin/poweroff", "poweroff", NULL); 242623ec8b0SRandy Fishel 243623ec8b0SRandy Fishel } 244623ec8b0SRandy Fishel 245623ec8b0SRandy Fishel /* 246623ec8b0SRandy Fishel * pm_check_suspend() - Check to see if suspend is supported/enabled 247623ec8b0SRandy Fishel * on this machine. 248623ec8b0SRandy Fishel * Ultimately, we would prefer to get the "default" suspend type from 249623ec8b0SRandy Fishel * a PM property or some other API, but for now, we know that STR is 250623ec8b0SRandy Fishel * only available on x86 and STD is only available on Sparc. It does 251623ec8b0SRandy Fishel * make this function quite easy, though. 252623ec8b0SRandy Fishel */ 253623ec8b0SRandy Fishel static int 254623ec8b0SRandy Fishel pm_check_suspend(void) { 255623ec8b0SRandy Fishel /* 256623ec8b0SRandy Fishel * Use the uadmin(2) "CHECK" command to see if suspend is supported 257623ec8b0SRandy Fishel */ 258623ec8b0SRandy Fishel return (uadmin(A_FREEZE, AD_CHECK_SUSPEND, 0)); 259623ec8b0SRandy Fishel } 260623ec8b0SRandy Fishel 261623ec8b0SRandy Fishel /* 262623ec8b0SRandy Fishel * This entry point _should_ be the common entry to suspend. It is in 263623ec8b0SRandy Fishel * it's entirety here, but would be best moved to libpower when that 264623ec8b0SRandy Fishel * is available. 265623ec8b0SRandy Fishel */ 266623ec8b0SRandy Fishel static void 267623ec8b0SRandy Fishel pm_suspend(void) 268623ec8b0SRandy Fishel { 269623ec8b0SRandy Fishel int cprarg = AD_SUSPEND; 270623ec8b0SRandy Fishel enum adt_uadmin_fcn fcn_id = ADT_FCN; 271623ec8b0SRandy Fishel au_event_t event_id = ADT_uadmin_freeze; 272623ec8b0SRandy Fishel adt_event_data_t *event = NULL; /* event to be generated */ 273623ec8b0SRandy Fishel adt_session_data_t *ah = NULL; /* audit session handle */ 274623ec8b0SRandy Fishel 275623ec8b0SRandy Fishel /* 276623ec8b0SRandy Fishel * Does the user have permission to use this command? 277623ec8b0SRandy Fishel */ 278623ec8b0SRandy Fishel if (chkauthattr(AUTHNAME_SUSPEND, user) != 1) { 279623ec8b0SRandy Fishel (void) printf(gettext("User %s does not have correct " 280623ec8b0SRandy Fishel "authorizations to suspend this machine.\n"), user); 281623ec8b0SRandy Fishel exit(1); 282623ec8b0SRandy Fishel } 283623ec8b0SRandy Fishel 284623ec8b0SRandy Fishel if (flags & LOWPOWER) { 285623ec8b0SRandy Fishel if (bringto_lowpower() == -1) { 286623ec8b0SRandy Fishel (void) printf(gettext("LowPower Failed\n")); 287623ec8b0SRandy Fishel exit(1); 288623ec8b0SRandy Fishel } 289623ec8b0SRandy Fishel } else if (flags & TEST) { 290623ec8b0SRandy Fishel /* 291623ec8b0SRandy Fishel * Test mode, do checks as if a real suspend, but 292623ec8b0SRandy Fishel * don't actually do the suspend. 293623ec8b0SRandy Fishel */ 294623ec8b0SRandy Fishel /* Check if suspend is supported */ 295623ec8b0SRandy Fishel if (pm_check_suspend() == -1) { 296623ec8b0SRandy Fishel suspend_error(errno); 297623ec8b0SRandy Fishel } 298623ec8b0SRandy Fishel 299623ec8b0SRandy Fishel (void) printf(gettext("TEST: Suspend would have been" 300623ec8b0SRandy Fishel " performed\n")); 301623ec8b0SRandy Fishel 302623ec8b0SRandy Fishel } else { 303623ec8b0SRandy Fishel /* Check if suspend is supported */ 304623ec8b0SRandy Fishel if (pm_check_suspend() == -1) { 305623ec8b0SRandy Fishel suspend_error(errno); 306623ec8b0SRandy Fishel } 307623ec8b0SRandy Fishel 308623ec8b0SRandy Fishel /* 309623ec8b0SRandy Fishel * We are about to suspend this machine, try and 310623ec8b0SRandy Fishel * lock the screen. We don't really care if this 311623ec8b0SRandy Fishel * succeeds or not, but that we actually tried. We 312623ec8b0SRandy Fishel * also know that we have sufficient privileges to 313623ec8b0SRandy Fishel * be here, so we lock the screen now, even if 314623ec8b0SRandy Fishel * suspend actually fails. 315623ec8b0SRandy Fishel * Note that garbage is sometimes displayed, and 316623ec8b0SRandy Fishel * we don't really care about it, so we toss all 317623ec8b0SRandy Fishel * text response. 318623ec8b0SRandy Fishel * it would also be good if there were another option 319623ec8b0SRandy Fishel * instead of launcing a file, as the disk might be 320623ec8b0SRandy Fishel * spun down if we are suspending due to idle. 321623ec8b0SRandy Fishel */ 322623ec8b0SRandy Fishel if (!(flags & NO_XLOCK)) { 323623ec8b0SRandy Fishel (void) system("/usr/bin/xdg-screensaver lock " 324623ec8b0SRandy Fishel " >/dev/null 2>&1"); 325623ec8b0SRandy Fishel } 326623ec8b0SRandy Fishel 327623ec8b0SRandy Fishel /* Time to do the actual deed! */ 328623ec8b0SRandy Fishel /* 329623ec8b0SRandy Fishel * Before we actually suspend, we need to audit and 330623ec8b0SRandy Fishel * "suspend" the audit files. 331623ec8b0SRandy Fishel */ 332623ec8b0SRandy Fishel /* set up audit session and event */ 333623ec8b0SRandy Fishel if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) == 0) { 334623ec8b0SRandy Fishel if ((event = adt_alloc_event(ah, event_id)) != NULL) { 335623ec8b0SRandy Fishel event->adt_uadmin_freeze.fcn = fcn_id; 336623ec8b0SRandy Fishel event->adt_uadmin_freeze.mdep = NULL; 337623ec8b0SRandy Fishel if (adt_put_event(event, ADT_SUCCESS, 0) != 0) { 338623ec8b0SRandy Fishel (void) fprintf(stderr, gettext( 339623ec8b0SRandy Fishel "%s: can't put audit event\n"), 340623ec8b0SRandy Fishel argvl[0]); 341623ec8b0SRandy Fishel } else { 342623ec8b0SRandy Fishel wait_for_auqueue(); 343623ec8b0SRandy Fishel } 344623ec8b0SRandy Fishel } 345623ec8b0SRandy Fishel (void) change_audit_file(); 346623ec8b0SRandy Fishel } else { 347623ec8b0SRandy Fishel (void) fprintf(stderr, gettext( 348623ec8b0SRandy Fishel "%s: can't start audit session\n"), argvl[0]); 349623ec8b0SRandy Fishel } 350623ec8b0SRandy Fishel 351623ec8b0SRandy Fishel if (uadmin(A_FREEZE, cprarg, 0) != 0) { 352623ec8b0SRandy Fishel (void) printf(gettext("Suspend Failed\n")); 353623ec8b0SRandy Fishel if (flags & FORCE) { 354623ec8b0SRandy Fishel /* 355623ec8b0SRandy Fishel * Note, that if we actually poweroff, 356623ec8b0SRandy Fishel * that the poweroff function will handle 357623ec8b0SRandy Fishel * that audit trail, and the resume 358623ec8b0SRandy Fishel * trail is effectively done. 359623ec8b0SRandy Fishel */ 360623ec8b0SRandy Fishel pm_poweroff(); 361623ec8b0SRandy Fishel } else { 362623ec8b0SRandy Fishel /* suspend_error() will exit. */ 363623ec8b0SRandy Fishel suspend_error(errno); 364623ec8b0SRandy Fishel /* 365623ec8b0SRandy Fishel * Audit the suspend failure and 366623ec8b0SRandy Fishel * reuse the event, but don't create one 367623ec8b0SRandy Fishel * if we don't already have one. 368623ec8b0SRandy Fishel */ 369623ec8b0SRandy Fishel if (event != NULL) { 37080148899SSurya Prakki (void) adt_put_event(event, 37180148899SSurya Prakki ADT_FAILURE, 0); 372623ec8b0SRandy Fishel } 373623ec8b0SRandy Fishel } 374623ec8b0SRandy Fishel } 375623ec8b0SRandy Fishel 376623ec8b0SRandy Fishel /* 377623ec8b0SRandy Fishel * Write the thaw event. 378623ec8b0SRandy Fishel */ 379623ec8b0SRandy Fishel if (ah != NULL) { 380623ec8b0SRandy Fishel if ((event == NULL) && 381623ec8b0SRandy Fishel ((event = adt_alloc_event(ah, ADT_uadmin_thaw)) 382623ec8b0SRandy Fishel == NULL)) { 383623ec8b0SRandy Fishel (void) fprintf(stderr, gettext( 384623ec8b0SRandy Fishel "%s: can't allocate thaw audit event\n"), 385623ec8b0SRandy Fishel argvl[0]); 386623ec8b0SRandy Fishel } else { 387623ec8b0SRandy Fishel event->adt_uadmin_thaw.fcn = fcn_id; 388623ec8b0SRandy Fishel if (adt_put_event(event, ADT_SUCCESS, 0) != 0) { 389623ec8b0SRandy Fishel (void) fprintf(stderr, gettext( 390623ec8b0SRandy Fishel "%s: can't put thaw audit event\n"), 391623ec8b0SRandy Fishel argvl[0]); 392623ec8b0SRandy Fishel } 393623ec8b0SRandy Fishel (void) adt_free_event(event); 394623ec8b0SRandy Fishel } 395623ec8b0SRandy Fishel } 396623ec8b0SRandy Fishel } 397623ec8b0SRandy Fishel if ((no_tty ? 0 : 1) && !(flags & NO_XLOCK)) { 398623ec8b0SRandy Fishel pm_do_auth(ah); 399623ec8b0SRandy Fishel } 400623ec8b0SRandy Fishel 401623ec8b0SRandy Fishel (void) adt_end_session(ah); 402623ec8b0SRandy Fishel } 403623ec8b0SRandy Fishel /* End of "library" functions */ 404623ec8b0SRandy Fishel 405623ec8b0SRandy Fishel /* 406623ec8b0SRandy Fishel * Print an appropriate error message and exit. 407623ec8b0SRandy Fishel */ 408623ec8b0SRandy Fishel 409623ec8b0SRandy Fishel static void 410623ec8b0SRandy Fishel suspend_error(int error) { 411623ec8b0SRandy Fishel 412623ec8b0SRandy Fishel switch (error) { 413623ec8b0SRandy Fishel case EBUSY: 414623ec8b0SRandy Fishel (void) printf(gettext("suspend: " 415623ec8b0SRandy Fishel "Suspend already in progress.\n\n")); 416623ec8b0SRandy Fishel exit(1); 417623ec8b0SRandy Fishel /*NOTREACHED*/ 418623ec8b0SRandy Fishel case ENOMEM: 419623ec8b0SRandy Fishel /*FALLTHROUGH*/ 420623ec8b0SRandy Fishel case ENOSPC: 421623ec8b0SRandy Fishel (void) printf(gettext("suspend: " 422623ec8b0SRandy Fishel "Not enough resources to suspend.\n\n")); 423623ec8b0SRandy Fishel exit(1); 424623ec8b0SRandy Fishel /*NOTREACHED*/ 425623ec8b0SRandy Fishel case ENOTSUP: 426623ec8b0SRandy Fishel (void) printf(gettext("suspend: " 427623ec8b0SRandy Fishel "Suspend is not supported.\n\n")); 428623ec8b0SRandy Fishel exit(1); 429623ec8b0SRandy Fishel /*NOTREACHED*/ 430623ec8b0SRandy Fishel case EPERM: 431623ec8b0SRandy Fishel (void) printf(gettext("suspend: " 432623ec8b0SRandy Fishel "Not sufficient privileges.\n\n")); 433623ec8b0SRandy Fishel exit(1); 434623ec8b0SRandy Fishel /*NOTREACHED*/ 435623ec8b0SRandy Fishel default: 436623ec8b0SRandy Fishel (void) printf(gettext("suspend: " 437623ec8b0SRandy Fishel "unknown error.\n\n")); 438623ec8b0SRandy Fishel exit(1); 439623ec8b0SRandy Fishel } 440623ec8b0SRandy Fishel 441623ec8b0SRandy Fishel } 442623ec8b0SRandy Fishel 443623ec8b0SRandy Fishel /* 444623ec8b0SRandy Fishel * refresh_dt() - Refresh screen when 'dtgreet' is running. 445623ec8b0SRandy Fishel * This is here for compatibility reasons, and could be removed once 446623ec8b0SRandy Fishel * dtgreet is no longer part of the system. 447623ec8b0SRandy Fishel */ 448623ec8b0SRandy Fishel static int 449623ec8b0SRandy Fishel refresh_dt() 450623ec8b0SRandy Fishel { 451623ec8b0SRandy Fishel int status; 452623ec8b0SRandy Fishel struct stat stat_buf; 453623ec8b0SRandy Fishel 454623ec8b0SRandy Fishel /* 455623ec8b0SRandy Fishel * If dtgreet exists, HUP it, otherwise just let screenlock 456623ec8b0SRandy Fishel * do it's thing. 457623ec8b0SRandy Fishel */ 458623ec8b0SRandy Fishel if ((stat("/usr/dt/bin/dtgreet", &stat_buf) == 0) && 459623ec8b0SRandy Fishel (stat_buf.st_mode & S_IXUSR)) { 460623ec8b0SRandy Fishel switch (fork()) { 461623ec8b0SRandy Fishel case -1: 462623ec8b0SRandy Fishel break; 463623ec8b0SRandy Fishel case 0: 464623ec8b0SRandy Fishel (void) close(1); 465623ec8b0SRandy Fishel (void) execl("/usr/bin/pkill", "pkill", 466623ec8b0SRandy Fishel "-HUP", "-u", "0", "-x", "dtgreet", NULL); 467623ec8b0SRandy Fishel break; 468623ec8b0SRandy Fishel default: 469623ec8b0SRandy Fishel (void) wait(&status); 470623ec8b0SRandy Fishel } 471623ec8b0SRandy Fishel } 472623ec8b0SRandy Fishel 473623ec8b0SRandy Fishel return (0); 474623ec8b0SRandy Fishel } 475623ec8b0SRandy Fishel 476623ec8b0SRandy Fishel #define DT_TMP "/var/dt/tmp" 477623ec8b0SRandy Fishel 478623ec8b0SRandy Fishel /* 479623ec8b0SRandy Fishel * On enter, the "xauthority" string has the value "XAUTHORITY=". On 480623ec8b0SRandy Fishel * return, if a Xauthority file is found, concatenate it to this string, 481623ec8b0SRandy Fishel * otherwise, return "xauthority" as it is. 482623ec8b0SRandy Fishel */ 483623ec8b0SRandy Fishel static char * 484623ec8b0SRandy Fishel get_xauthority(char *xauthority) 485623ec8b0SRandy Fishel { 486623ec8b0SRandy Fishel pid_t uid; 487623ec8b0SRandy Fishel char *home_dir; 488623ec8b0SRandy Fishel struct passwd *pwd; 489623ec8b0SRandy Fishel char filepath[MAXPATHLEN]; 490623ec8b0SRandy Fishel struct stat stat_buf; 491623ec8b0SRandy Fishel DIR *dirp; 492623ec8b0SRandy Fishel struct dirent *dp; 493623ec8b0SRandy Fishel char xauth[MAXPATHLEN] = ""; 494623ec8b0SRandy Fishel time_t latest = 0; 495623ec8b0SRandy Fishel 496623ec8b0SRandy Fishel uid = getuid(); 497623ec8b0SRandy Fishel 498623ec8b0SRandy Fishel /* 499623ec8b0SRandy Fishel * Determine home directory of the user. 500623ec8b0SRandy Fishel */ 501623ec8b0SRandy Fishel if ((home_dir = getenv("HOME")) == NULL) { 502623ec8b0SRandy Fishel if ((pwd = getpwuid(uid)) == NULL) { 50380148899SSurya Prakki (void) printf(gettext("Error: unable to get passwd " 504623ec8b0SRandy Fishel "entry for user.\n")); 505623ec8b0SRandy Fishel exit(1); 506623ec8b0SRandy Fishel } 507623ec8b0SRandy Fishel home_dir = pwd->pw_dir; 508623ec8b0SRandy Fishel } 509623ec8b0SRandy Fishel if ((strlen(home_dir) + sizeof ("/.Xauthority")) >= MAXPATHLEN) { 51080148899SSurya Prakki (void) printf(gettext("Error: path to home directory is too " 511623ec8b0SRandy Fishel "long.\n")); 512623ec8b0SRandy Fishel exit(1); 513623ec8b0SRandy Fishel } 514623ec8b0SRandy Fishel 515623ec8b0SRandy Fishel /* 516623ec8b0SRandy Fishel * If there is a .Xauthority file in home directory, reference it. 517623ec8b0SRandy Fishel */ 518623ec8b0SRandy Fishel /*LINTED*/ 519623ec8b0SRandy Fishel (void) sprintf(filepath, "%s/.Xauthority", home_dir); 520623ec8b0SRandy Fishel if (stat(filepath, &stat_buf) == 0) 521623ec8b0SRandy Fishel return (strcat(xauthority, filepath)); 522623ec8b0SRandy Fishel 523623ec8b0SRandy Fishel /* 524623ec8b0SRandy Fishel * If Xsession can not access user's home directory, it creates the 525623ec8b0SRandy Fishel * Xauthority file in "/var/dt/tmp" directory. Since the exact 526623ec8b0SRandy Fishel * name of the Xauthority is not known, search the directory and 527623ec8b0SRandy Fishel * find the last changed file that starts with ".Xauth" and owned 528623ec8b0SRandy Fishel * by the user. Hopefully, that is the valid Xauthority file for 529623ec8b0SRandy Fishel * the current X session. 530623ec8b0SRandy Fishel */ 531623ec8b0SRandy Fishel if ((dirp = opendir(DT_TMP)) == NULL) 532623ec8b0SRandy Fishel return (xauthority); 533623ec8b0SRandy Fishel 534623ec8b0SRandy Fishel while ((dp = readdir(dirp)) != NULL) { 535623ec8b0SRandy Fishel if (strstr(dp->d_name, ".Xauth") != NULL) { 536623ec8b0SRandy Fishel /*LINTED*/ 537623ec8b0SRandy Fishel (void) sprintf(filepath, "%s/%s", DT_TMP, dp->d_name); 538623ec8b0SRandy Fishel if (stat(filepath, &stat_buf) == -1) 539623ec8b0SRandy Fishel continue; 540623ec8b0SRandy Fishel if (stat_buf.st_uid != uid) 541623ec8b0SRandy Fishel continue; 542623ec8b0SRandy Fishel if (stat_buf.st_ctime > latest) { 543623ec8b0SRandy Fishel (void) strcpy(xauth, filepath); 544623ec8b0SRandy Fishel latest = stat_buf.st_ctime; 545623ec8b0SRandy Fishel } 546623ec8b0SRandy Fishel } 547623ec8b0SRandy Fishel } 548623ec8b0SRandy Fishel (void) closedir(dirp); 549623ec8b0SRandy Fishel 550623ec8b0SRandy Fishel return (strcat(xauthority, xauth)); 551623ec8b0SRandy Fishel } 552623ec8b0SRandy Fishel 553623ec8b0SRandy Fishel /* 554623ec8b0SRandy Fishel * suspend can be called in following ways: 555623ec8b0SRandy Fishel * 1. from daemon (powerd) for auto-shutdown. 556623ec8b0SRandy Fishel * a. there might be a OW/CDE environment 557623ec8b0SRandy Fishel * b. there might not be any windowing environment 558623ec8b0SRandy Fishel * 2. by a user entered command. 559623ec8b0SRandy Fishel * a. the command can be entered from a cmdtool type OW/CDE tool 560623ec8b0SRandy Fishel * b. the command can be entered by a user logged in on a dumb 561623ec8b0SRandy Fishel * terminal. 562623ec8b0SRandy Fishel * i) there might be a OW/CDE running on console 563623ec8b0SRandy Fishel * and we have permission to talk to it. 564623ec8b0SRandy Fishel * ii) there is no OW/CDE running on console or we 565623ec8b0SRandy Fishel * don't have permission to talk to it or console 566623ec8b0SRandy Fishel * itself is the dumb terminal we have logged into. 567623ec8b0SRandy Fishel * 568623ec8b0SRandy Fishel * In main(), we decide on the correct case and call appropriate functions. 569623ec8b0SRandy Fishel */ 570623ec8b0SRandy Fishel 571623ec8b0SRandy Fishel int 572623ec8b0SRandy Fishel main(int argc, char **argv) 573623ec8b0SRandy Fishel { 574623ec8b0SRandy Fishel int c; 575623ec8b0SRandy Fishel char display_name[MAXNAMELEN + 9] = "DISPLAY="; 576623ec8b0SRandy Fishel char xauthority[MAXPATHLEN + 12] = "XAUTHORITY="; 577623ec8b0SRandy Fishel struct passwd *pw; 578623ec8b0SRandy Fishel 579*5009f788SIgor Kozhukhov (void) signal(SIGHUP, SIG_IGN); 580*5009f788SIgor Kozhukhov (void) signal(SIGINT, SIG_IGN); 581*5009f788SIgor Kozhukhov (void) signal(SIGQUIT, SIG_IGN); 582*5009f788SIgor Kozhukhov (void) signal(SIGTSTP, SIG_IGN); 583*5009f788SIgor Kozhukhov (void) signal(SIGTTIN, SIG_IGN); 584*5009f788SIgor Kozhukhov (void) signal(SIGTTOU, SIG_IGN); 585623ec8b0SRandy Fishel 586623ec8b0SRandy Fishel /* 587623ec8b0SRandy Fishel * If suspend is invoked from a daemon (case 1 above), it 588623ec8b0SRandy Fishel * will not have a working stdin, stdout and stderr. We need 589623ec8b0SRandy Fishel * these to print proper error messages and possibly get user 590623ec8b0SRandy Fishel * input. We attach them to console and hope that attachment 591623ec8b0SRandy Fishel * works. 592623ec8b0SRandy Fishel */ 593623ec8b0SRandy Fishel if (ttyname(0) == NULL) { 594623ec8b0SRandy Fishel no_tty = 1; 59580148899SSurya Prakki (void) dup2(open("/dev/console", O_RDONLY), 0); 59680148899SSurya Prakki (void) dup2(open("/dev/console", O_WRONLY), 1); 59780148899SSurya Prakki (void) dup2(open("/dev/console", O_WRONLY), 2); 598623ec8b0SRandy Fishel } 599623ec8b0SRandy Fishel 600623ec8b0SRandy Fishel while ((c = getopt(argc, argv, "fnxhtd:")) != EOF) { 601623ec8b0SRandy Fishel switch (c) { 602623ec8b0SRandy Fishel case 'f': 603623ec8b0SRandy Fishel /* 604623ec8b0SRandy Fishel * Force machine to poweroff if 605623ec8b0SRandy Fishel * suspend fails 606623ec8b0SRandy Fishel */ 607623ec8b0SRandy Fishel flags |= FORCE; 608623ec8b0SRandy Fishel break; 609623ec8b0SRandy Fishel case 'n': 610623ec8b0SRandy Fishel /* No warning popups - Obsolete */ 611623ec8b0SRandy Fishel flags |= NO_WARN; 612623ec8b0SRandy Fishel break; 613623ec8b0SRandy Fishel case 'x': 614623ec8b0SRandy Fishel /* Don't try to screenlock */ 615623ec8b0SRandy Fishel flags |= NO_XLOCK; 616623ec8b0SRandy Fishel break; 617623ec8b0SRandy Fishel case 'h': 618623ec8b0SRandy Fishel /* Do a shutdown instead of suspend */ 619623ec8b0SRandy Fishel flags |= SHUTDOWN; 620623ec8b0SRandy Fishel break; 621623ec8b0SRandy Fishel case 'd': 622623ec8b0SRandy Fishel /* Needswork */ 623623ec8b0SRandy Fishel /* Set the DISPLAY value in the environment */ 624623ec8b0SRandy Fishel if (strlen(optarg) >= MAXNAMELEN) { 625623ec8b0SRandy Fishel (void) printf(gettext("Error: " 626623ec8b0SRandy Fishel "display name is too long.\n")); 627623ec8b0SRandy Fishel return (1); 628623ec8b0SRandy Fishel } 629623ec8b0SRandy Fishel (void) strcat(display_name, optarg); 630623ec8b0SRandy Fishel if (putenv(display_name) != 0) { 631623ec8b0SRandy Fishel (void) printf(gettext("Error: " 632623ec8b0SRandy Fishel "unable to set DISPLAY " 633623ec8b0SRandy Fishel "environment variable.\n")); 634623ec8b0SRandy Fishel return (1); 635623ec8b0SRandy Fishel } 636623ec8b0SRandy Fishel break; 637623ec8b0SRandy Fishel case 't': 638623ec8b0SRandy Fishel /* Test, don't actually do any operation */ 639623ec8b0SRandy Fishel flags |= TEST; 640623ec8b0SRandy Fishel break; 641623ec8b0SRandy Fishel default: 642623ec8b0SRandy Fishel (void) printf(gettext("USAGE: suspend " 643623ec8b0SRandy Fishel "[-fnxh] [-d <display>]\n")); 644623ec8b0SRandy Fishel return (1); 645623ec8b0SRandy Fishel } 646623ec8b0SRandy Fishel } 647623ec8b0SRandy Fishel 648623ec8b0SRandy Fishel /* 649623ec8b0SRandy Fishel * The action of pressing power key and power button on a MOU-3 machine 650623ec8b0SRandy Fishel * causes suspend being invoked with SYSSUSPENDDODEFAULT 651623ec8b0SRandy Fishel * enviromental variable set - indicating the default action is machine 652623ec8b0SRandy Fishel * dependent: for MOU-3 type machine, "LowPower" mode is the default, 653623ec8b0SRandy Fishel * for all the rest, "Suspend" is the default. Existing suspend 654623ec8b0SRandy Fishel * flags works the same. 655623ec8b0SRandy Fishel */ 656623ec8b0SRandy Fishel if (getenv("SYSSUSPENDDODEFAULT")) 657623ec8b0SRandy Fishel if (is_mou3()) 658623ec8b0SRandy Fishel flags |= LOWPOWER; 659623ec8b0SRandy Fishel 660623ec8b0SRandy Fishel if ((flags & FORCE) && (flags & LOWPOWER)) 661623ec8b0SRandy Fishel flags &= ~LOWPOWER; 662623ec8b0SRandy Fishel 663623ec8b0SRandy Fishel /* 664623ec8b0SRandy Fishel * Flag "-h" overrides flag "-f". 665623ec8b0SRandy Fishel */ 666623ec8b0SRandy Fishel if ((flags & SHUTDOWN) && (flags & FORCE)) 667623ec8b0SRandy Fishel flags &= ~(FORCE | LOWPOWER); 668623ec8b0SRandy Fishel 669623ec8b0SRandy Fishel if (flags & FORCE) 670623ec8b0SRandy Fishel flags |= NO_WARN; 671623ec8b0SRandy Fishel 672623ec8b0SRandy Fishel /* 673623ec8b0SRandy Fishel * Check initally if the user has the authorizations to 674623ec8b0SRandy Fishel * do either a suspend or shutdown. pm_suspend() will also 675623ec8b0SRandy Fishel * make this test, so we could defer till then, but if we 676623ec8b0SRandy Fishel * do it now, we at least prevent a lot of unneeded setup. 677623ec8b0SRandy Fishel */ 678623ec8b0SRandy Fishel pw = getpwuid(getuid()); 67980148899SSurya Prakki (void) strncpy(user, pw->pw_name, NMAX); 680623ec8b0SRandy Fishel 681623ec8b0SRandy Fishel if ((flags & (FORCE|SHUTDOWN)) && 682623ec8b0SRandy Fishel (chkauthattr(AUTHNAME_SHUTDOWN, pw->pw_name) != 1)) { 683623ec8b0SRandy Fishel (void) printf(gettext("User does not have correct " 684623ec8b0SRandy Fishel "authorizations to shutdown the machine.\n")); 685623ec8b0SRandy Fishel exit(1); 686623ec8b0SRandy Fishel } 687623ec8b0SRandy Fishel if (!(flags & SHUTDOWN) && 688623ec8b0SRandy Fishel (chkauthattr(AUTHNAME_SUSPEND, pw->pw_name) != 1)) { 689623ec8b0SRandy Fishel (void) printf(gettext("User does not have correct " 690623ec8b0SRandy Fishel "authorizations to suspend.\n")); 691623ec8b0SRandy Fishel exit(1); 692623ec8b0SRandy Fishel } 693623ec8b0SRandy Fishel 694623ec8b0SRandy Fishel /* 695623ec8b0SRandy Fishel * If we are only shutting down, there isn't much to do, just 696623ec8b0SRandy Fishel * call pm_poweroff(), and let it do all the work. 697623ec8b0SRandy Fishel */ 698623ec8b0SRandy Fishel if (flags & SHUTDOWN) { 699623ec8b0SRandy Fishel /* 700623ec8b0SRandy Fishel * pm_poweroff either powers off or exits, 701623ec8b0SRandy Fishel * so there is no return. 702623ec8b0SRandy Fishel */ 703623ec8b0SRandy Fishel if (flags & TEST) { 704623ec8b0SRandy Fishel (void) printf("TEST: This machine would have " 705623ec8b0SRandy Fishel "powered off\n"); 706623ec8b0SRandy Fishel exit(1); 707623ec8b0SRandy Fishel } else { 708623ec8b0SRandy Fishel pm_poweroff(); 709623ec8b0SRandy Fishel } 710623ec8b0SRandy Fishel /* NOTREACHED */ 711623ec8b0SRandy Fishel } 712623ec8b0SRandy Fishel 713623ec8b0SRandy Fishel /* 714623ec8b0SRandy Fishel * If XAUTHORITY environment variable is not set, try to set 715623ec8b0SRandy Fishel * one up. 716623ec8b0SRandy Fishel */ 717623ec8b0SRandy Fishel if (getenv("XAUTHORITY") == NULL) 718623ec8b0SRandy Fishel (void) putenv(get_xauthority(xauthority)); 719623ec8b0SRandy Fishel 720623ec8b0SRandy Fishel /* 721623ec8b0SRandy Fishel * In case of "suspend" being called from daemon "powerd", 722623ec8b0SRandy Fishel * signal SIGALRM is blocked so use "sigset()" instead of "signal()". 723623ec8b0SRandy Fishel */ 724*5009f788SIgor Kozhukhov (void) sigset(SIGALRM, alarm_handler); 725623ec8b0SRandy Fishel 726623ec8b0SRandy Fishel /* Call the "suspend" function to do the last of the work */ 727623ec8b0SRandy Fishel pm_suspend(); 728623ec8b0SRandy Fishel 729623ec8b0SRandy Fishel if (refresh_dt() == -1) { 73080148899SSurya Prakki (void) printf("%s: Failed to refresh screen.\n", argv[0]); 731623ec8b0SRandy Fishel return (1); 732623ec8b0SRandy Fishel } 733623ec8b0SRandy Fishel return (0); 734623ec8b0SRandy Fishel } 735623ec8b0SRandy Fishel 736623ec8b0SRandy Fishel #include <sys/pm.h> 737623ec8b0SRandy Fishel 738623ec8b0SRandy Fishel /* 739623ec8b0SRandy Fishel * Note that some of these functions are more relevant to Sparc platforms, 740623ec8b0SRandy Fishel * but they do function properly on other platforms, they just don't do 741623ec8b0SRandy Fishel * as much. 742623ec8b0SRandy Fishel */ 743623ec8b0SRandy Fishel /* 744623ec8b0SRandy Fishel * bringto_lowpower() 745623ec8b0SRandy Fishel * This tells the PM framework to put the devices it controls in an idle 746623ec8b0SRandy Fishel * state. The framework only complains if a device that *must* be idle 747623ec8b0SRandy Fishel * doesn't succeed in getting there. 748623ec8b0SRandy Fishel */ 749623ec8b0SRandy Fishel static int 750623ec8b0SRandy Fishel bringto_lowpower() 751623ec8b0SRandy Fishel { 752623ec8b0SRandy Fishel int fd; 753623ec8b0SRandy Fishel 754623ec8b0SRandy Fishel if ((fd = open("/dev/pm", O_RDWR)) < 0) { 75580148899SSurya Prakki (void) printf(gettext("Can't open /dev/pm\n")); 756623ec8b0SRandy Fishel return (-1); 757623ec8b0SRandy Fishel } 758623ec8b0SRandy Fishel 759623ec8b0SRandy Fishel if (ioctl(fd, PM_IDLE_DOWN, NULL) < 0) { 76080148899SSurya Prakki (void) printf(gettext("Failed to bring system " 76180148899SSurya Prakki "to low power mode.\n")); 76280148899SSurya Prakki (void) close(fd); 763623ec8b0SRandy Fishel return (-1); 764623ec8b0SRandy Fishel } 76580148899SSurya Prakki (void) close(fd); 766623ec8b0SRandy Fishel return (0); 767623ec8b0SRandy Fishel } 768623ec8b0SRandy Fishel 769623ec8b0SRandy Fishel #include <sys/cpr.h> 770623ec8b0SRandy Fishel 771623ec8b0SRandy Fishel /* 772623ec8b0SRandy Fishel * Though this test is predominantly used on Sparc, it will run on other 773623ec8b0SRandy Fishel * platforms, and might be usefull one day on those. 774623ec8b0SRandy Fishel */ 775623ec8b0SRandy Fishel static int 776623ec8b0SRandy Fishel is_mou3() 777623ec8b0SRandy Fishel { 778623ec8b0SRandy Fishel struct cprconfig cf; 779623ec8b0SRandy Fishel int fd; 780623ec8b0SRandy Fishel int found = 0; 781623ec8b0SRandy Fishel 782623ec8b0SRandy Fishel if ((fd = open(CPR_CONFIG, O_RDONLY)) < 0) { 78380148899SSurya Prakki (void) printf(gettext("Can't open /etc/.cpr_config file.")); 784623ec8b0SRandy Fishel return (found); 785623ec8b0SRandy Fishel } 786623ec8b0SRandy Fishel 787623ec8b0SRandy Fishel if (read(fd, (void *) &cf, sizeof (cf)) != sizeof (cf)) { 78880148899SSurya Prakki (void) printf(gettext("Can't read /etc/.cpr_config file.")); 789623ec8b0SRandy Fishel } else { 790623ec8b0SRandy Fishel found = cf.is_autopm_default; 791623ec8b0SRandy Fishel } 792623ec8b0SRandy Fishel 79380148899SSurya Prakki (void) close(fd); 794623ec8b0SRandy Fishel return (found); 795623ec8b0SRandy Fishel } 796623ec8b0SRandy Fishel 797623ec8b0SRandy Fishel /* 798623ec8b0SRandy Fishel * Reauthenticate the user on return from suspend. 799623ec8b0SRandy Fishel * This is here and not in the PAM-specific file, as there are 800623ec8b0SRandy Fishel * items specific to sys-suspend, and not generic to PAM. This may 801623ec8b0SRandy Fishel * become part of a future PM library. The audit handle is passed, 802623ec8b0SRandy Fishel * as the pm_suspend code actually starts an audit session, so it 803623ec8b0SRandy Fishel * makes sense to just continue to use it. If it were separated 804623ec8b0SRandy Fishel * from the pm_suspend code, it will need to open a new session. 805623ec8b0SRandy Fishel */ 806623ec8b0SRandy Fishel #define DEF_ATTEMPTS 3 807623ec8b0SRandy Fishel static void 808623ec8b0SRandy Fishel pm_do_auth(adt_session_data_t *ah) 809623ec8b0SRandy Fishel { 810623ec8b0SRandy Fishel pam_handle_t *pm_pamh; 811623ec8b0SRandy Fishel int err; 812623ec8b0SRandy Fishel int pam_flag = 0; 813623ec8b0SRandy Fishel int chpasswd_tries; 814623ec8b0SRandy Fishel struct pam_conv pam_conv = {pam_tty_conv, NULL}; 815623ec8b0SRandy Fishel 816623ec8b0SRandy Fishel if (user[0] == '\0') 817623ec8b0SRandy Fishel return; 818623ec8b0SRandy Fishel 819623ec8b0SRandy Fishel if ((err = pam_start("sys-suspend", user, &pam_conv, 820623ec8b0SRandy Fishel &pm_pamh)) != PAM_SUCCESS) 821623ec8b0SRandy Fishel return; 822623ec8b0SRandy Fishel 823623ec8b0SRandy Fishel pam_flag = PAM_DISALLOW_NULL_AUTHTOK; 824623ec8b0SRandy Fishel 825623ec8b0SRandy Fishel do { 826623ec8b0SRandy Fishel err = pam_authenticate(pm_pamh, pam_flag); 827623ec8b0SRandy Fishel 828623ec8b0SRandy Fishel if (err == PAM_SUCCESS) { 829623ec8b0SRandy Fishel err = pam_acct_mgmt(pm_pamh, pam_flag); 830623ec8b0SRandy Fishel 831623ec8b0SRandy Fishel if (err == PAM_NEW_AUTHTOK_REQD) { 832623ec8b0SRandy Fishel chpasswd_tries = 0; 833623ec8b0SRandy Fishel 834623ec8b0SRandy Fishel do { 835623ec8b0SRandy Fishel err = pam_chauthtok(pm_pamh, 836623ec8b0SRandy Fishel PAM_CHANGE_EXPIRED_AUTHTOK); 837623ec8b0SRandy Fishel chpasswd_tries++; 838623ec8b0SRandy Fishel 839623ec8b0SRandy Fishel } while ((err == PAM_AUTHTOK_ERR || 840623ec8b0SRandy Fishel err == PAM_TRY_AGAIN) && 841623ec8b0SRandy Fishel chpasswd_tries < DEF_ATTEMPTS); 842623ec8b0SRandy Fishel pm_audit_event(ah, ADT_passwd, err); 843623ec8b0SRandy Fishel } 844623ec8b0SRandy Fishel err = pam_setcred(pm_pamh, PAM_REFRESH_CRED); 845623ec8b0SRandy Fishel } 846623ec8b0SRandy Fishel if (err != PAM_SUCCESS) { 847623ec8b0SRandy Fishel (void) fprintf(stdout, "%s\n", 848623ec8b0SRandy Fishel pam_strerror(pm_pamh, err)); 849623ec8b0SRandy Fishel pm_audit_event(ah, ADT_screenunlock, err); 850623ec8b0SRandy Fishel } 851623ec8b0SRandy Fishel } while (err != PAM_SUCCESS); 852623ec8b0SRandy Fishel pm_audit_event(ah, ADT_passwd, 0); 853623ec8b0SRandy Fishel 854623ec8b0SRandy Fishel (void) pam_end(pm_pamh, err); 855623ec8b0SRandy Fishel } 856