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
pm_audit_event(adt_session_data_t * ah,au_event_t event_id,int status)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
change_audit_file(void)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
wait_for_auqueue()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
alarm_handler(int sig)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
pm_poweroff(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
pm_check_suspend(void)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
pm_suspend(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
suspend_error(int error)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
refresh_dt()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 *
get_xauthority(char * xauthority)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
main(int argc,char ** argv)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
bringto_lowpower()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
is_mou3()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
pm_do_auth(adt_session_data_t * ah)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