xref: /illumos-gate/usr/src/cmd/vt/vtdaemon.c (revision bbf21555)
1aecfc01dSrui zang - Sun Microsystems - Beijing China /*
2aecfc01dSrui zang - Sun Microsystems - Beijing China  * CDDL HEADER START
3aecfc01dSrui zang - Sun Microsystems - Beijing China  *
4aecfc01dSrui zang - Sun Microsystems - Beijing China  * The contents of this file are subject to the terms of the
5aecfc01dSrui zang - Sun Microsystems - Beijing China  * Common Development and Distribution License (the "License").
6aecfc01dSrui zang - Sun Microsystems - Beijing China  * You may not use this file except in compliance with the License.
7aecfc01dSrui zang - Sun Microsystems - Beijing China  *
8aecfc01dSrui zang - Sun Microsystems - Beijing China  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9aecfc01dSrui zang - Sun Microsystems - Beijing China  * or http://www.opensolaris.org/os/licensing.
10aecfc01dSrui zang - Sun Microsystems - Beijing China  * See the License for the specific language governing permissions
11aecfc01dSrui zang - Sun Microsystems - Beijing China  * and limitations under the License.
12aecfc01dSrui zang - Sun Microsystems - Beijing China  *
13aecfc01dSrui zang - Sun Microsystems - Beijing China  * When distributing Covered Code, include this CDDL HEADER in each
14aecfc01dSrui zang - Sun Microsystems - Beijing China  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15aecfc01dSrui zang - Sun Microsystems - Beijing China  * If applicable, add the following below this CDDL HEADER, with the
16aecfc01dSrui zang - Sun Microsystems - Beijing China  * fields enclosed by brackets "[]" replaced with your own identifying
17aecfc01dSrui zang - Sun Microsystems - Beijing China  * information: Portions Copyright [yyyy] [name of copyright owner]
18aecfc01dSrui zang - Sun Microsystems - Beijing China  *
19aecfc01dSrui zang - Sun Microsystems - Beijing China  * CDDL HEADER END
20aecfc01dSrui zang - Sun Microsystems - Beijing China  */
21aecfc01dSrui zang - Sun Microsystems - Beijing China 
22aecfc01dSrui zang - Sun Microsystems - Beijing China /*
23b52f1647SZhao Edgar Liu - Sun Microsystems  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24aecfc01dSrui zang - Sun Microsystems - Beijing China  */
25aecfc01dSrui zang - Sun Microsystems - Beijing China 
26aecfc01dSrui zang - Sun Microsystems - Beijing China /*
27aecfc01dSrui zang - Sun Microsystems - Beijing China  * vtdaemon is responsible for the session secure switch via hotkeys.
28aecfc01dSrui zang - Sun Microsystems - Beijing China  *
29*bbf21555SRichard Lowe  * vtdaemon itself, like ttymon(8), is also running on a virtual
30aecfc01dSrui zang - Sun Microsystems - Beijing China  * console device (/dev/vt/1), and provides a text console session
31aecfc01dSrui zang - Sun Microsystems - Beijing China  * for password input and authentication. The /dev/vt/1 special text
32aecfc01dSrui zang - Sun Microsystems - Beijing China  * console is reserved and end users cannot switch to it via hotkeys.
33aecfc01dSrui zang - Sun Microsystems - Beijing China  *
34aecfc01dSrui zang - Sun Microsystems - Beijing China  *
35aecfc01dSrui zang - Sun Microsystems - Beijing China  * The hotkey event request can come from either kernel or Xserver,
36aecfc01dSrui zang - Sun Microsystems - Beijing China  * and a door server is setup to handle the request:
37aecfc01dSrui zang - Sun Microsystems - Beijing China  *
38aecfc01dSrui zang - Sun Microsystems - Beijing China  *   1) All text console hotkeys (e.g. "Alt + F#") are intercepted by
39aecfc01dSrui zang - Sun Microsystems - Beijing China  *      the kernel console driver which sends a door upcall to the
40aecfc01dSrui zang - Sun Microsystems - Beijing China  *      vtdaemon via door_upcall (target_vt).
41aecfc01dSrui zang - Sun Microsystems - Beijing China  *
42aecfc01dSrui zang - Sun Microsystems - Beijing China  *   2) All Xserver hotkeys ("Alt + Ctrl + F#") are intercepted by
43aecfc01dSrui zang - Sun Microsystems - Beijing China  *      Xserver which sends a door call to the vtdaemon via
44aecfc01dSrui zang - Sun Microsystems - Beijing China  *      door_call (target_vt).
45aecfc01dSrui zang - Sun Microsystems - Beijing China  *
46aecfc01dSrui zang - Sun Microsystems - Beijing China  *
47aecfc01dSrui zang - Sun Microsystems - Beijing China  * server_for_door receives and handles any door server requests:
48aecfc01dSrui zang - Sun Microsystems - Beijing China  *
49aecfc01dSrui zang - Sun Microsystems - Beijing China  *   Firstly, check source session:
50aecfc01dSrui zang - Sun Microsystems - Beijing China  *
51aecfc01dSrui zang - Sun Microsystems - Beijing China  *      . If it's from kernel for a text console source session,
52aecfc01dSrui zang - Sun Microsystems - Beijing China  *        then directly go to check the target session.
53aecfc01dSrui zang - Sun Microsystems - Beijing China  *
54aecfc01dSrui zang - Sun Microsystems - Beijing China  *      . If it's from Xserver for a graphical source session and the vt
55aecfc01dSrui zang - Sun Microsystems - Beijing China  *        associated with the Xserver is currently active:
56aecfc01dSrui zang - Sun Microsystems - Beijing China  *          check if a user has logged in, if true, issue an internal
57aecfc01dSrui zang - Sun Microsystems - Beijing China  *          VT_EV_LOCK event to the main thread to request lock for
58aecfc01dSrui zang - Sun Microsystems - Beijing China  *          the graphical source session; else, directly go to check
59aecfc01dSrui zang - Sun Microsystems - Beijing China  *          the target session.
60aecfc01dSrui zang - Sun Microsystems - Beijing China  *
61aecfc01dSrui zang - Sun Microsystems - Beijing China  *      . otherwise, discard this request.
62aecfc01dSrui zang - Sun Microsystems - Beijing China  *
63aecfc01dSrui zang - Sun Microsystems - Beijing China  *
64aecfc01dSrui zang - Sun Microsystems - Beijing China  *    Secondly, check the target session
65aecfc01dSrui zang - Sun Microsystems - Beijing China  *
66aecfc01dSrui zang - Sun Microsystems - Beijing China  *      . if the target session is a text one that no one has logged in
67aecfc01dSrui zang - Sun Microsystems - Beijing China  *        or a graphical one, issue an internal VT_EV_ACTIVATE event to
68aecfc01dSrui zang - Sun Microsystems - Beijing China  *        the main thread to request the actual VT switch.
69aecfc01dSrui zang - Sun Microsystems - Beijing China  *
70aecfc01dSrui zang - Sun Microsystems - Beijing China  *      . otherwise, the target session is a text one that someone has
71aecfc01dSrui zang - Sun Microsystems - Beijing China  *        logged in, issue an internal VT_EV_AUTH event to the main
72aecfc01dSrui zang - Sun Microsystems - Beijing China  *        thread to request authentication for the target session.
73aecfc01dSrui zang - Sun Microsystems - Beijing China  *
74aecfc01dSrui zang - Sun Microsystems - Beijing China  *
75aecfc01dSrui zang - Sun Microsystems - Beijing China  * The main thread of vtdaemon is a loop waiting for internal events
76aecfc01dSrui zang - Sun Microsystems - Beijing China  * which come from door call threads:
77aecfc01dSrui zang - Sun Microsystems - Beijing China  *
78aecfc01dSrui zang - Sun Microsystems - Beijing China  *   1)  VT_EV_AUTH      to authenticate for target session:
79aecfc01dSrui zang - Sun Microsystems - Beijing China  *
80aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       firstly switch to the vtdaemon special text console;
81aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       then prompt for password (target_owner on target_vt),
82aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       e.g. "User Bob's password on vt/#: ".
83aecfc01dSrui zang - Sun Microsystems - Beijing China  *
84aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       if the password is correct (authentication succeeds),
85aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       then actually issue the VT switch; otherwise, ignore
86aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       the request.
87aecfc01dSrui zang - Sun Microsystems - Beijing China  *
88aecfc01dSrui zang - Sun Microsystems - Beijing China  *   2)  VT_EV_LOCK      to lock the graphical source session:
89aecfc01dSrui zang - Sun Microsystems - Beijing China  *
90aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       activate screenlock for this graphical session.
91aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       vtdaemon just invokes existing front-end command line
92aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       tools (e.g. xscreensaver-command -lock for JDS) to
93aecfc01dSrui zang - Sun Microsystems - Beijing China  *                       lock the display.
94aecfc01dSrui zang - Sun Microsystems - Beijing China  *
95aecfc01dSrui zang - Sun Microsystems - Beijing China  *   3)  VT_EV_ACTIVATE  to directly switch to the target session
96aecfc01dSrui zang - Sun Microsystems - Beijing China  *
97aecfc01dSrui zang - Sun Microsystems - Beijing China  *
98aecfc01dSrui zang - Sun Microsystems - Beijing China  * There is a system/vtdaemon:default SMF service for vtdaemon.
99aecfc01dSrui zang - Sun Microsystems - Beijing China  *
100aecfc01dSrui zang - Sun Microsystems - Beijing China  *	There's a "hotkeys" property (BOOLEAN) in the
101aecfc01dSrui zang - Sun Microsystems - Beijing China  *	system/vtdaemon:default SMF service, which allows authorized
102aecfc01dSrui zang - Sun Microsystems - Beijing China  *	users to dynamically enable or disable VT switch via hotkeys.
103aecfc01dSrui zang - Sun Microsystems - Beijing China  *      Its default value is TRUE (enabled).
104aecfc01dSrui zang - Sun Microsystems - Beijing China  *
105aecfc01dSrui zang - Sun Microsystems - Beijing China  *	There's a "secure" property (BOOLEAN) in the
106aecfc01dSrui zang - Sun Microsystems - Beijing China  *	system/vtdaemon:default SMF service, which allows authorized
107aecfc01dSrui zang - Sun Microsystems - Beijing China  *	users to dynamically enable or disable hotkeys are secure.
108aecfc01dSrui zang - Sun Microsystems - Beijing China  *	If disabled, the user can freely switch to any session without
109aecfc01dSrui zang - Sun Microsystems - Beijing China  *	authentication. Its default value is TRUE (enabled).
110aecfc01dSrui zang - Sun Microsystems - Beijing China  *
111aecfc01dSrui zang - Sun Microsystems - Beijing China  *
112aecfc01dSrui zang - Sun Microsystems - Beijing China  *  By default, there's only 16 virtual console device nodes (from
113aecfc01dSrui zang - Sun Microsystems - Beijing China  *  /dev/vt/0 to /dev/vt/15). There's a property "nodecount"
114aecfc01dSrui zang - Sun Microsystems - Beijing China  *  (default value is 16) in the system/vtdaemon:default SMF
115aecfc01dSrui zang - Sun Microsystems - Beijing China  *  service, so authorized users can configure it to have more
116aecfc01dSrui zang - Sun Microsystems - Beijing China  *  or less virtual console device nodes.
117aecfc01dSrui zang - Sun Microsystems - Beijing China  *
118aecfc01dSrui zang - Sun Microsystems - Beijing China  *  Xserver needs to switch back to previous active vt via VT_EV_X_EXIT
119aecfc01dSrui zang - Sun Microsystems - Beijing China  *  door event request when it's exiting, so vtdaemon always needs to
120aecfc01dSrui zang - Sun Microsystems - Beijing China  *  be there even if the hotkeys switch is disabled, otherwise the screen
121aecfc01dSrui zang - Sun Microsystems - Beijing China  *  will be just blank when Xserver exits.
122aecfc01dSrui zang - Sun Microsystems - Beijing China  */
123aecfc01dSrui zang - Sun Microsystems - Beijing China 
124aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/param.h>
125aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/mman.h>
126aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/types.h>
127aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/wait.h>
128aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/stat.h>
129aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sysmacros.h>
130aecfc01dSrui zang - Sun Microsystems - Beijing China #include <syslog.h>
131aecfc01dSrui zang - Sun Microsystems - Beijing China #include <deflt.h>
132aecfc01dSrui zang - Sun Microsystems - Beijing China 
133aecfc01dSrui zang - Sun Microsystems - Beijing China #include <bsm/adt.h>
134aecfc01dSrui zang - Sun Microsystems - Beijing China #include <bsm/adt_event.h>
135aecfc01dSrui zang - Sun Microsystems - Beijing China 
136aecfc01dSrui zang - Sun Microsystems - Beijing China #include <alloca.h>
137aecfc01dSrui zang - Sun Microsystems - Beijing China #include <assert.h>
138aecfc01dSrui zang - Sun Microsystems - Beijing China #include <errno.h>
139aecfc01dSrui zang - Sun Microsystems - Beijing China #include <door.h>
140aecfc01dSrui zang - Sun Microsystems - Beijing China #include <fcntl.h>
141aecfc01dSrui zang - Sun Microsystems - Beijing China #include <signal.h>
142aecfc01dSrui zang - Sun Microsystems - Beijing China #include <stdarg.h>
143aecfc01dSrui zang - Sun Microsystems - Beijing China #include <stdio.h>
144aecfc01dSrui zang - Sun Microsystems - Beijing China #include <stdlib.h>
145aecfc01dSrui zang - Sun Microsystems - Beijing China #include <string.h>
146aecfc01dSrui zang - Sun Microsystems - Beijing China #include <strings.h>
147aecfc01dSrui zang - Sun Microsystems - Beijing China #include <synch.h>
148aecfc01dSrui zang - Sun Microsystems - Beijing China #include <thread.h>
149aecfc01dSrui zang - Sun Microsystems - Beijing China #include <unistd.h>
150aecfc01dSrui zang - Sun Microsystems - Beijing China #include <wait.h>
151aecfc01dSrui zang - Sun Microsystems - Beijing China #include <limits.h>
152aecfc01dSrui zang - Sun Microsystems - Beijing China #include <zone.h>
153aecfc01dSrui zang - Sun Microsystems - Beijing China #include <priv.h>
154aecfc01dSrui zang - Sun Microsystems - Beijing China #include <pwd.h>
155aecfc01dSrui zang - Sun Microsystems - Beijing China #include <utmpx.h>
156aecfc01dSrui zang - Sun Microsystems - Beijing China #include <procfs.h>
157aecfc01dSrui zang - Sun Microsystems - Beijing China #include <poll.h>
158aecfc01dSrui zang - Sun Microsystems - Beijing China #include <termio.h>
159aecfc01dSrui zang - Sun Microsystems - Beijing China #include <security/pam_appl.h>
160aecfc01dSrui zang - Sun Microsystems - Beijing China #include <time.h>
161aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/console.h>
162aecfc01dSrui zang - Sun Microsystems - Beijing China #include <assert.h>
163aecfc01dSrui zang - Sun Microsystems - Beijing China #include <syslog.h>
164aecfc01dSrui zang - Sun Microsystems - Beijing China 
165aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/vt.h>
166aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/vtdaemon.h>
167aecfc01dSrui zang - Sun Microsystems - Beijing China 
168aecfc01dSrui zang - Sun Microsystems - Beijing China /*
169aecfc01dSrui zang - Sun Microsystems - Beijing China  * The door file /var/run/vt/vtdaemon_door
170aecfc01dSrui zang - Sun Microsystems - Beijing China  */
171aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_TMPDIR "/var/run/vt"
172aecfc01dSrui zang - Sun Microsystems - Beijing China 
173aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_DAEMON_ARG	0
174aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_DAEMON_CONSOLE_FILE	"/dev/vt/1"
175aecfc01dSrui zang - Sun Microsystems - Beijing China 
176aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_IS_SYSTEM_CONSOLE(vtno)	((vtno) == 1)
177aecfc01dSrui zang - Sun Microsystems - Beijing China 
178aecfc01dSrui zang - Sun Microsystems - Beijing China /* Defaults for updating expired passwords */
179aecfc01dSrui zang - Sun Microsystems - Beijing China #define	DEF_ATTEMPTS	3
180aecfc01dSrui zang - Sun Microsystems - Beijing China 
181aecfc01dSrui zang - Sun Microsystems - Beijing China int daemonfd;
182aecfc01dSrui zang - Sun Microsystems - Beijing China 
183aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t vt_hotkeys = B_TRUE;		/* '-k' option to disable */
184aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t vt_secure = B_TRUE;		/* '-s' option to disable */
185aecfc01dSrui zang - Sun Microsystems - Beijing China 
186aecfc01dSrui zang - Sun Microsystems - Beijing China static char	vt_door_path[MAXPATHLEN];
187aecfc01dSrui zang - Sun Microsystems - Beijing China static int	vt_door = -1;
188aecfc01dSrui zang - Sun Microsystems - Beijing China 
189aecfc01dSrui zang - Sun Microsystems - Beijing China /* protecting vt_hotkeys_pending and vt_auth_doing */
190aecfc01dSrui zang - Sun Microsystems - Beijing China static mutex_t	vt_mutex = DEFAULTMUTEX;
191aecfc01dSrui zang - Sun Microsystems - Beijing China 
192aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t vt_hotkeys_pending = B_FALSE;
193aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t vt_auth_doing = B_FALSE;
194aecfc01dSrui zang - Sun Microsystems - Beijing China 
195aecfc01dSrui zang - Sun Microsystems - Beijing China static adt_session_data_t **vt_ah_array = NULL;
196aecfc01dSrui zang - Sun Microsystems - Beijing China static int vtnodecount = 0;
197aecfc01dSrui zang - Sun Microsystems - Beijing China 
198aecfc01dSrui zang - Sun Microsystems - Beijing China static int vt_audit_start(adt_session_data_t **, pid_t);
199aecfc01dSrui zang - Sun Microsystems - Beijing China static void vt_audit_event(adt_session_data_t *, au_event_t, int);
200aecfc01dSrui zang - Sun Microsystems - Beijing China static void vt_check_source_audit(void);
201aecfc01dSrui zang - Sun Microsystems - Beijing China 
202aecfc01dSrui zang - Sun Microsystems - Beijing China static int
vt_setup_signal(int signo,int mask)203aecfc01dSrui zang - Sun Microsystems - Beijing China vt_setup_signal(int signo, int mask)
204aecfc01dSrui zang - Sun Microsystems - Beijing China {
205aecfc01dSrui zang - Sun Microsystems - Beijing China 	sigset_t set;
206aecfc01dSrui zang - Sun Microsystems - Beijing China 
207aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) sigemptyset(&set);
208aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) sigaddset(&set, signo);
209aecfc01dSrui zang - Sun Microsystems - Beijing China 
210aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (mask)
211aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (sigprocmask(SIG_BLOCK, &set, NULL));
212aecfc01dSrui zang - Sun Microsystems - Beijing China 	else
213aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (sigprocmask(SIG_UNBLOCK, &set, NULL));
214aecfc01dSrui zang - Sun Microsystems - Beijing China }
215aecfc01dSrui zang - Sun Microsystems - Beijing China 
216aecfc01dSrui zang - Sun Microsystems - Beijing China static void
do_activate_screenlock(int display_num)217aecfc01dSrui zang - Sun Microsystems - Beijing China do_activate_screenlock(int display_num)
218aecfc01dSrui zang - Sun Microsystems - Beijing China {
219aecfc01dSrui zang - Sun Microsystems - Beijing China 	char dpy[16];
220aecfc01dSrui zang - Sun Microsystems - Beijing China 
221aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) snprintf(dpy, sizeof (dpy), "%d", display_num);
222aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) execl("/usr/lib/vtxlock", "vtxlock", dpy, NULL);
223aecfc01dSrui zang - Sun Microsystems - Beijing China }
224aecfc01dSrui zang - Sun Microsystems - Beijing China 
225aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_activate_screenlock(int display)226aecfc01dSrui zang - Sun Microsystems - Beijing China vt_activate_screenlock(int display)
227aecfc01dSrui zang - Sun Microsystems - Beijing China {
228aecfc01dSrui zang - Sun Microsystems - Beijing China 	pid_t pid;
229aecfc01dSrui zang - Sun Microsystems - Beijing China 
230aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((pid = fork()) == -1)
231aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
232aecfc01dSrui zang - Sun Microsystems - Beijing China 
233aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pid == 0) { /* child */
234aecfc01dSrui zang - Sun Microsystems - Beijing China 		do_activate_screenlock(display);
235aecfc01dSrui zang - Sun Microsystems - Beijing China 		exit(0);
236aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
237aecfc01dSrui zang - Sun Microsystems - Beijing China 
238aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* parent */
239aecfc01dSrui zang - Sun Microsystems - Beijing China 	while (waitpid(pid, (int *)0, 0) != pid)
240aecfc01dSrui zang - Sun Microsystems - Beijing China 		continue;
241aecfc01dSrui zang - Sun Microsystems - Beijing China }
242aecfc01dSrui zang - Sun Microsystems - Beijing China 
243aecfc01dSrui zang - Sun Microsystems - Beijing China /*
244aecfc01dSrui zang - Sun Microsystems - Beijing China  * Find the login process and user logged in on the target vt.
245aecfc01dSrui zang - Sun Microsystems - Beijing China  */
246aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_read_utx(int target_vt,pid_t * pid,char name[])247aecfc01dSrui zang - Sun Microsystems - Beijing China vt_read_utx(int target_vt, pid_t *pid, char name[])
248aecfc01dSrui zang - Sun Microsystems - Beijing China {
249aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct utmpx  *u;
250aecfc01dSrui zang - Sun Microsystems - Beijing China 	char ttyntail[sizeof (u->ut_line)];
251aecfc01dSrui zang - Sun Microsystems - Beijing China 
252aecfc01dSrui zang - Sun Microsystems - Beijing China 	*pid = (pid_t)-1;
253aecfc01dSrui zang - Sun Microsystems - Beijing China 
254aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (VT_IS_SYSTEM_CONSOLE(target_vt)) /* system console */
255aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) snprintf(ttyntail, sizeof (ttyntail),
256aecfc01dSrui zang - Sun Microsystems - Beijing China 		    "%s", "console");
257aecfc01dSrui zang - Sun Microsystems - Beijing China 	else
258aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) snprintf(ttyntail, sizeof (ttyntail),
259aecfc01dSrui zang - Sun Microsystems - Beijing China 		    "%s%d", "vt/", target_vt);
260aecfc01dSrui zang - Sun Microsystems - Beijing China 
261aecfc01dSrui zang - Sun Microsystems - Beijing China 	setutxent();
262aecfc01dSrui zang - Sun Microsystems - Beijing China 	while ((u = getutxent()) != NULL)
263aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* see if this is the entry we want */
264aecfc01dSrui zang - Sun Microsystems - Beijing China 		if ((u->ut_type == USER_PROCESS) &&
265aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (!nonuserx(*u)) &&
266aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (u->ut_host[0] == '\0') &&
267aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (strncmp(u->ut_line, ttyntail, sizeof (u->ut_line)) == 0)) {
268aecfc01dSrui zang - Sun Microsystems - Beijing China 
269aecfc01dSrui zang - Sun Microsystems - Beijing China 			*pid = u->ut_pid;
270aecfc01dSrui zang - Sun Microsystems - Beijing China 			if (name != NULL) {
271aecfc01dSrui zang - Sun Microsystems - Beijing China 				(void) strncpy(name, u->ut_user,
272aecfc01dSrui zang - Sun Microsystems - Beijing China 				    sizeof (u->ut_user));
273aecfc01dSrui zang - Sun Microsystems - Beijing China 				name[sizeof (u->ut_user)] = '\0';
274aecfc01dSrui zang - Sun Microsystems - Beijing China 			}
275aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
276aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
277aecfc01dSrui zang - Sun Microsystems - Beijing China 
278aecfc01dSrui zang - Sun Microsystems - Beijing China 	endutxent();
279aecfc01dSrui zang - Sun Microsystems - Beijing China }
280aecfc01dSrui zang - Sun Microsystems - Beijing China 
281aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
vt_is_tipline(void)282aecfc01dSrui zang - Sun Microsystems - Beijing China vt_is_tipline(void)
283aecfc01dSrui zang - Sun Microsystems - Beijing China {
284aecfc01dSrui zang - Sun Microsystems - Beijing China 	static int is_tipline = 0;
285aecfc01dSrui zang - Sun Microsystems - Beijing China 	int fd;
286aecfc01dSrui zang - Sun Microsystems - Beijing China 	static char termbuf[MAX_TERM_TYPE_LEN];
287aecfc01dSrui zang - Sun Microsystems - Beijing China 	static struct cons_getterm cons_term = { sizeof (termbuf), termbuf};
288aecfc01dSrui zang - Sun Microsystems - Beijing China 
289aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (is_tipline != 0)
290aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (is_tipline == 1);
291aecfc01dSrui zang - Sun Microsystems - Beijing China 
292aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((fd = open("/dev/console", O_RDONLY)) < 0)
293aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
294aecfc01dSrui zang - Sun Microsystems - Beijing China 
295aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ioctl(fd, CONS_GETTERM, &cons_term) != 0 &&
296aecfc01dSrui zang - Sun Microsystems - Beijing China 	    errno == ENODEV) {
297aecfc01dSrui zang - Sun Microsystems - Beijing China 		is_tipline = 1;
298aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else {
299aecfc01dSrui zang - Sun Microsystems - Beijing China 		is_tipline = -1;
300aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
301aecfc01dSrui zang - Sun Microsystems - Beijing China 
302aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) close(fd);
303aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (is_tipline == 1);
304aecfc01dSrui zang - Sun Microsystems - Beijing China }
305aecfc01dSrui zang - Sun Microsystems - Beijing China 
306aecfc01dSrui zang - Sun Microsystems - Beijing China static int
validate_target_vt(int target_vt)307aecfc01dSrui zang - Sun Microsystems - Beijing China validate_target_vt(int target_vt)
308aecfc01dSrui zang - Sun Microsystems - Beijing China {
309aecfc01dSrui zang - Sun Microsystems - Beijing China 	int fd;
310aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vt_stat state;
311aecfc01dSrui zang - Sun Microsystems - Beijing China 
312aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (target_vt < 1)
313aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
314aecfc01dSrui zang - Sun Microsystems - Beijing China 
315aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_WRONLY)) < 0)
316aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
317aecfc01dSrui zang - Sun Microsystems - Beijing China 
318aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ioctl(fd, VT_GETSTATE, &state) != 0) {
319aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) close(fd);
320aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
321aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
322aecfc01dSrui zang - Sun Microsystems - Beijing China 
323aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) close(fd);
324aecfc01dSrui zang - Sun Microsystems - Beijing China 
325aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (state.v_active == target_vt) {
326aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);	/* it's current active vt */
327aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
328aecfc01dSrui zang - Sun Microsystems - Beijing China 
329aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (target_vt == 1) {
330aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
331aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * In tipline case, the system console is always
332aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * available, so ignore this request.
333aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
334aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (vt_is_tipline())
335aecfc01dSrui zang - Sun Microsystems - Beijing China 			return (-1);
336aecfc01dSrui zang - Sun Microsystems - Beijing China 
337aecfc01dSrui zang - Sun Microsystems - Beijing China 		target_vt = 0;
338aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
339aecfc01dSrui zang - Sun Microsystems - Beijing China 
340aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
341aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * The hotkey request and corresponding target_vt number can come
342aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * from either kernel or Xserver (or other user applications).
343aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * In kernel we've validated the hotkey request, but Xserver (or
344aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * other user applications) cannot do it, so here we still try
345aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * to validate it.
346aecfc01dSrui zang - Sun Microsystems - Beijing China 	 *
347aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * VT_GETSTATE is only valid for first 16 VTs for historical reasons.
348aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Fortunately, in practice, Xserver can only send the hotkey
349aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * request of target_vt number from 1 to 12 (Ctrl + Alt + F1 to F2).
350aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
351aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (target_vt < 8 * sizeof (state.v_state)) {
352aecfc01dSrui zang - Sun Microsystems - Beijing China 		if ((state.v_state & (1 << target_vt)) != 0) {
353aecfc01dSrui zang - Sun Microsystems - Beijing China 			return (0);
354aecfc01dSrui zang - Sun Microsystems - Beijing China 		} else {
355aecfc01dSrui zang - Sun Microsystems - Beijing China 			return (-1);
356aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
357aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
358aecfc01dSrui zang - Sun Microsystems - Beijing China 
359aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (0);
360aecfc01dSrui zang - Sun Microsystems - Beijing China }
361aecfc01dSrui zang - Sun Microsystems - Beijing China 
362aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_do_activate(int target_vt)363aecfc01dSrui zang - Sun Microsystems - Beijing China vt_do_activate(int target_vt)
364aecfc01dSrui zang - Sun Microsystems - Beijing China {
365aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ioctl(daemonfd, VT_ACTIVATE, target_vt);
366aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_lock(&vt_mutex);
367aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_hotkeys_pending = B_FALSE;
368aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_unlock(&vt_mutex);
369aecfc01dSrui zang - Sun Microsystems - Beijing China }
370aecfc01dSrui zang - Sun Microsystems - Beijing China 
371aecfc01dSrui zang - Sun Microsystems - Beijing China /* events written to fd 0 and read from fd 1 */
372aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_EV_AUTH	1
373aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_EV_LOCK	2
374aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_EV_ACTIVATE	3
375aecfc01dSrui zang - Sun Microsystems - Beijing China 
376aecfc01dSrui zang - Sun Microsystems - Beijing China /* events written to fd 1 and read from fd 0 */
377aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_EV_TERMINATE_AUTH	4
378aecfc01dSrui zang - Sun Microsystems - Beijing China 
379aecfc01dSrui zang - Sun Microsystems - Beijing China typedef struct vt_evt {
380aecfc01dSrui zang - Sun Microsystems - Beijing China 	int	ve_cmd;
381aecfc01dSrui zang - Sun Microsystems - Beijing China 	int	ve_info;	/* vtno or display num */
382aecfc01dSrui zang - Sun Microsystems - Beijing China } vt_evt_t;
383aecfc01dSrui zang - Sun Microsystems - Beijing China 
384aecfc01dSrui zang - Sun Microsystems - Beijing China static int eventstream[2];
385aecfc01dSrui zang - Sun Microsystems - Beijing China 
386aecfc01dSrui zang - Sun Microsystems - Beijing China boolean_t
eventstream_init(void)387aecfc01dSrui zang - Sun Microsystems - Beijing China eventstream_init(void)
388aecfc01dSrui zang - Sun Microsystems - Beijing China {
389aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pipe(eventstream) == -1)
390aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
391aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (B_TRUE);
392aecfc01dSrui zang - Sun Microsystems - Beijing China }
393aecfc01dSrui zang - Sun Microsystems - Beijing China 
394aecfc01dSrui zang - Sun Microsystems - Beijing China void
eventstream_write(int channel,vt_evt_t * pevt)395aecfc01dSrui zang - Sun Microsystems - Beijing China eventstream_write(int channel, vt_evt_t *pevt)
396aecfc01dSrui zang - Sun Microsystems - Beijing China {
397aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) write(eventstream[channel], pevt, sizeof (vt_evt_t));
398aecfc01dSrui zang - Sun Microsystems - Beijing China }
399aecfc01dSrui zang - Sun Microsystems - Beijing China 
400aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
eventstream_read(int channel,vt_evt_t * pevt)401aecfc01dSrui zang - Sun Microsystems - Beijing China eventstream_read(int channel, vt_evt_t *pevt)
402aecfc01dSrui zang - Sun Microsystems - Beijing China {
403aecfc01dSrui zang - Sun Microsystems - Beijing China 	ssize_t rval;
404aecfc01dSrui zang - Sun Microsystems - Beijing China 
405aecfc01dSrui zang - Sun Microsystems - Beijing China 	rval = read(eventstream[channel], pevt, sizeof (vt_evt_t));
406aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (rval > 0);
407aecfc01dSrui zang - Sun Microsystems - Beijing China }
408aecfc01dSrui zang - Sun Microsystems - Beijing China 
409aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_ev_request(int cmd,int info)410aecfc01dSrui zang - Sun Microsystems - Beijing China vt_ev_request(int cmd, int info)
411aecfc01dSrui zang - Sun Microsystems - Beijing China {
412aecfc01dSrui zang - Sun Microsystems - Beijing China 	int channel;
413aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_evt_t ve;
414aecfc01dSrui zang - Sun Microsystems - Beijing China 
415aecfc01dSrui zang - Sun Microsystems - Beijing China 	ve.ve_cmd = cmd;
416aecfc01dSrui zang - Sun Microsystems - Beijing China 	ve.ve_info = info;
417aecfc01dSrui zang - Sun Microsystems - Beijing China 
418aecfc01dSrui zang - Sun Microsystems - Beijing China 	channel = (cmd == VT_EV_TERMINATE_AUTH) ? 1 : 0;
419aecfc01dSrui zang - Sun Microsystems - Beijing China 	eventstream_write(channel, &ve);
420aecfc01dSrui zang - Sun Microsystems - Beijing China }
421aecfc01dSrui zang - Sun Microsystems - Beijing China 
422aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_clear_events(void)423aecfc01dSrui zang - Sun Microsystems - Beijing China vt_clear_events(void)
424aecfc01dSrui zang - Sun Microsystems - Beijing China {
425aecfc01dSrui zang - Sun Microsystems - Beijing China 	int rval = 0;
426aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct stat buf;
427aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_evt_t evt;
428aecfc01dSrui zang - Sun Microsystems - Beijing China 
429aecfc01dSrui zang - Sun Microsystems - Beijing China 	while (rval == 0) {
430aecfc01dSrui zang - Sun Microsystems - Beijing China 		rval = fstat(eventstream[0], &buf);
431aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (rval != -1 && buf.st_size > 0)
432aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) eventstream_read(0, &evt);
433aecfc01dSrui zang - Sun Microsystems - Beijing China 		else
434aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
435aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
436aecfc01dSrui zang - Sun Microsystems - Beijing China }
437aecfc01dSrui zang - Sun Microsystems - Beijing China 
438aecfc01dSrui zang - Sun Microsystems - Beijing China static int vt_conv(int, struct pam_message **,
439aecfc01dSrui zang - Sun Microsystems - Beijing China     struct pam_response **, void *);
440aecfc01dSrui zang - Sun Microsystems - Beijing China 
441aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED*/
442aecfc01dSrui zang - Sun Microsystems - Beijing China static void
catch(int x)443aecfc01dSrui zang - Sun Microsystems - Beijing China catch(int x)
444aecfc01dSrui zang - Sun Microsystems - Beijing China {
445aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) signal(SIGINT, catch);
446aecfc01dSrui zang - Sun Microsystems - Beijing China }
447aecfc01dSrui zang - Sun Microsystems - Beijing China 
448aecfc01dSrui zang - Sun Microsystems - Beijing China /*
449aecfc01dSrui zang - Sun Microsystems - Beijing China  * The SIGINT (ctl_c) will restart the authentication, and re-prompt
450aecfc01dSrui zang - Sun Microsystems - Beijing China  * the end user to input the password.
451aecfc01dSrui zang - Sun Microsystems - Beijing China  */
452aecfc01dSrui zang - Sun Microsystems - Beijing China static int
vt_poll()453aecfc01dSrui zang - Sun Microsystems - Beijing China vt_poll()
454aecfc01dSrui zang - Sun Microsystems - Beijing China {
455aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct pollfd pollfds[2];
456aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_evt_t ve;
457aecfc01dSrui zang - Sun Microsystems - Beijing China 	int ret;
458aecfc01dSrui zang - Sun Microsystems - Beijing China 
459aecfc01dSrui zang - Sun Microsystems - Beijing China 	pollfds[0].fd = eventstream[0];
460aecfc01dSrui zang - Sun Microsystems - Beijing China 	pollfds[1].fd = daemonfd;
461aecfc01dSrui zang - Sun Microsystems - Beijing China 	pollfds[0].events = pollfds[1].events =
462aecfc01dSrui zang - Sun Microsystems - Beijing China 	    POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
463aecfc01dSrui zang - Sun Microsystems - Beijing China 
464aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (;;) {
465aecfc01dSrui zang - Sun Microsystems - Beijing China 		pollfds[0].revents = pollfds[1].revents = 0;
466aecfc01dSrui zang - Sun Microsystems - Beijing China 
467aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = poll(pollfds,
468aecfc01dSrui zang - Sun Microsystems - Beijing China 		    sizeof (pollfds) / sizeof (struct pollfd), -1);
469aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (ret == -1 && errno != EINTR) {
470aecfc01dSrui zang - Sun Microsystems - Beijing China 			continue;
471aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
472aecfc01dSrui zang - Sun Microsystems - Beijing China 
473aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (ret == -1 && errno == EINTR)
474aecfc01dSrui zang - Sun Microsystems - Beijing China 			return (-1);
475aecfc01dSrui zang - Sun Microsystems - Beijing China 
476aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (pollfds[0].revents) {
477aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) eventstream_read(0, &ve);
478aecfc01dSrui zang - Sun Microsystems - Beijing China 			return (0);
479aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
480aecfc01dSrui zang - Sun Microsystems - Beijing China 
481aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (pollfds[1].revents)
482aecfc01dSrui zang - Sun Microsystems - Beijing China 			return (1);
483aecfc01dSrui zang - Sun Microsystems - Beijing China 
484aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (0);
485aecfc01dSrui zang - Sun Microsystems - Beijing China 
486aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
487aecfc01dSrui zang - Sun Microsystems - Beijing China }
488aecfc01dSrui zang - Sun Microsystems - Beijing China 
489aecfc01dSrui zang - Sun Microsystems - Beijing China static char
vt_getchar(int fd)490aecfc01dSrui zang - Sun Microsystems - Beijing China vt_getchar(int fd)
491aecfc01dSrui zang - Sun Microsystems - Beijing China {
492aecfc01dSrui zang - Sun Microsystems - Beijing China 	char c;
493aecfc01dSrui zang - Sun Microsystems - Beijing China 	int cnt;
494aecfc01dSrui zang - Sun Microsystems - Beijing China 
495aecfc01dSrui zang - Sun Microsystems - Beijing China 	cnt = read(fd, &c, 1);
496aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (cnt > 0) {
497aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (c);
498aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
499aecfc01dSrui zang - Sun Microsystems - Beijing China 
500aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (EOF);
501aecfc01dSrui zang - Sun Microsystems - Beijing China }
502aecfc01dSrui zang - Sun Microsystems - Beijing China 
503aecfc01dSrui zang - Sun Microsystems - Beijing China static char *
vt_getinput(int noecho)504aecfc01dSrui zang - Sun Microsystems - Beijing China vt_getinput(int noecho)
505aecfc01dSrui zang - Sun Microsystems - Beijing China {
506aecfc01dSrui zang - Sun Microsystems - Beijing China 	int c;
507aecfc01dSrui zang - Sun Microsystems - Beijing China 	int i = 0;
508aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct termio tty;
509aecfc01dSrui zang - Sun Microsystems - Beijing China 	tcflag_t tty_flags;
510aecfc01dSrui zang - Sun Microsystems - Beijing China 	char input[PAM_MAX_RESP_SIZE];
511aecfc01dSrui zang - Sun Microsystems - Beijing China 
512aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (noecho) {
513aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ioctl(daemonfd, TCGETA, &tty);
514aecfc01dSrui zang - Sun Microsystems - Beijing China 		tty_flags = tty.c_lflag;
515aecfc01dSrui zang - Sun Microsystems - Beijing China 		tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
516aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ioctl(daemonfd, TCSETAF, &tty);
517aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
518aecfc01dSrui zang - Sun Microsystems - Beijing China 
519aecfc01dSrui zang - Sun Microsystems - Beijing China 	while ((vt_poll()) == 1) {
520aecfc01dSrui zang - Sun Microsystems - Beijing China 		if ((c = vt_getchar(daemonfd)) != '\n' && c != '\r' &&
521b52f1647SZhao Edgar Liu - Sun Microsystems 		    c != EOF && (i < PAM_MAX_RESP_SIZE - 1))
522aecfc01dSrui zang - Sun Microsystems - Beijing China 			input[i++] = (char)c;
523aecfc01dSrui zang - Sun Microsystems - Beijing China 		else
524aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
525aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
526aecfc01dSrui zang - Sun Microsystems - Beijing China 
527aecfc01dSrui zang - Sun Microsystems - Beijing China 	input[i] = '\0';
528aecfc01dSrui zang - Sun Microsystems - Beijing China 
529aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (noecho) {
530aecfc01dSrui zang - Sun Microsystems - Beijing China 		tty.c_lflag = tty_flags;
531aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ioctl(daemonfd, TCSETAW, &tty);
532aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) fputc('\n', stdout);
533aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
534aecfc01dSrui zang - Sun Microsystems - Beijing China 
535aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (strdup(input));
536aecfc01dSrui zang - Sun Microsystems - Beijing China }
537aecfc01dSrui zang - Sun Microsystems - Beijing China 
538aecfc01dSrui zang - Sun Microsystems - Beijing China /*
539aecfc01dSrui zang - Sun Microsystems - Beijing China  * vt_conv: vtdaemon PAM conversation function.
540aecfc01dSrui zang - Sun Microsystems - Beijing China  * SIGINT/EINTR is handled in vt_getinput()/vt_poll().
541aecfc01dSrui zang - Sun Microsystems - Beijing China  */
542aecfc01dSrui zang - Sun Microsystems - Beijing China 
543aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED*/
544aecfc01dSrui zang - Sun Microsystems - Beijing China static int
vt_conv(int num_msg,struct pam_message ** msg,struct pam_response ** response,void * appdata_ptr)545aecfc01dSrui zang - Sun Microsystems - Beijing China vt_conv(int num_msg, struct pam_message **msg,
546aecfc01dSrui zang - Sun Microsystems - Beijing China     struct pam_response **response, void *appdata_ptr)
547aecfc01dSrui zang - Sun Microsystems - Beijing China {
548aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct pam_message	*m;
549aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct pam_response	*r;
550aecfc01dSrui zang - Sun Microsystems - Beijing China 	int			i, k;
551aecfc01dSrui zang - Sun Microsystems - Beijing China 
552aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (num_msg >= PAM_MAX_NUM_MSG) {
553aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "too many messages %d >= %d",
554aecfc01dSrui zang - Sun Microsystems - Beijing China 		    num_msg, PAM_MAX_NUM_MSG);
555aecfc01dSrui zang - Sun Microsystems - Beijing China 		*response = NULL;
556aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (PAM_CONV_ERR);
557aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
558aecfc01dSrui zang - Sun Microsystems - Beijing China 
559aecfc01dSrui zang - Sun Microsystems - Beijing China 	*response = calloc(num_msg, sizeof (struct pam_response));
560aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (*response == NULL)
561aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (PAM_BUF_ERR);
562aecfc01dSrui zang - Sun Microsystems - Beijing China 
563aecfc01dSrui zang - Sun Microsystems - Beijing China 	m = *msg;
564aecfc01dSrui zang - Sun Microsystems - Beijing China 	r = *response;
565aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (i = 0; i < num_msg; i++) {
566aecfc01dSrui zang - Sun Microsystems - Beijing China 		int echo_off = 0;
567aecfc01dSrui zang - Sun Microsystems - Beijing China 
568aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* Bad message */
569aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (m->msg == NULL) {
570aecfc01dSrui zang - Sun Microsystems - Beijing China 			syslog(LOG_ERR, "message[%d]: %d/NULL\n",
571aecfc01dSrui zang - Sun Microsystems - Beijing China 			    i, m->msg_style);
572aecfc01dSrui zang - Sun Microsystems - Beijing China 			goto err;
573aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
574aecfc01dSrui zang - Sun Microsystems - Beijing China 
575aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
576aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Fix up final newline:
577aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * remove from prompts, add back for messages.
578aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
579aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (m->msg[strlen(m->msg)] == '\n')
580aecfc01dSrui zang - Sun Microsystems - Beijing China 			m->msg[strlen(m->msg)] = '\0';
581aecfc01dSrui zang - Sun Microsystems - Beijing China 
582aecfc01dSrui zang - Sun Microsystems - Beijing China 		r->resp = NULL;
583aecfc01dSrui zang - Sun Microsystems - Beijing China 		r->resp_retcode = 0;
584aecfc01dSrui zang - Sun Microsystems - Beijing China 
585aecfc01dSrui zang - Sun Microsystems - Beijing China 		switch (m->msg_style) {
586aecfc01dSrui zang - Sun Microsystems - Beijing China 
587aecfc01dSrui zang - Sun Microsystems - Beijing China 		case PAM_PROMPT_ECHO_OFF:
588aecfc01dSrui zang - Sun Microsystems - Beijing China 			echo_off = 1;
589aecfc01dSrui zang - Sun Microsystems - Beijing China 			/* FALLTHROUGH */
590aecfc01dSrui zang - Sun Microsystems - Beijing China 
591aecfc01dSrui zang - Sun Microsystems - Beijing China 		case PAM_PROMPT_ECHO_ON:
592aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fputs(m->msg, stdout);
593aecfc01dSrui zang - Sun Microsystems - Beijing China 
594aecfc01dSrui zang - Sun Microsystems - Beijing China 			r->resp = vt_getinput(echo_off);
595aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
596aecfc01dSrui zang - Sun Microsystems - Beijing China 
597aecfc01dSrui zang - Sun Microsystems - Beijing China 		case PAM_ERROR_MSG:
598aecfc01dSrui zang - Sun Microsystems - Beijing China 			/* the user may want to see this */
599aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fputs(m->msg, stdout);
600aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fputs("\n", stdout);
601aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
602aecfc01dSrui zang - Sun Microsystems - Beijing China 
603aecfc01dSrui zang - Sun Microsystems - Beijing China 		case PAM_TEXT_INFO:
604aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fputs(m->msg, stdout);
605aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fputs("\n", stdout);
606aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
607aecfc01dSrui zang - Sun Microsystems - Beijing China 
608aecfc01dSrui zang - Sun Microsystems - Beijing China 		default:
609aecfc01dSrui zang - Sun Microsystems - Beijing China 			syslog(LOG_ERR, "message[%d]: unknown type"
610aecfc01dSrui zang - Sun Microsystems - Beijing China 			    "%d/val=\"%s\"", i, m->msg_style, m->msg);
611aecfc01dSrui zang - Sun Microsystems - Beijing China 
612aecfc01dSrui zang - Sun Microsystems - Beijing China 			/* error, service module won't clean up */
613aecfc01dSrui zang - Sun Microsystems - Beijing China 			goto err;
614aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
615aecfc01dSrui zang - Sun Microsystems - Beijing China 
616aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* Next message/response */
617aecfc01dSrui zang - Sun Microsystems - Beijing China 		m++;
618aecfc01dSrui zang - Sun Microsystems - Beijing China 		r++;
619aecfc01dSrui zang - Sun Microsystems - Beijing China 
620aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
621aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (PAM_SUCCESS);
622aecfc01dSrui zang - Sun Microsystems - Beijing China 
623aecfc01dSrui zang - Sun Microsystems - Beijing China err:
624aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
625aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Service modules don't clean up responses if an error is returned.
626aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Free responses here.
627aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
628aecfc01dSrui zang - Sun Microsystems - Beijing China 	r = *response;
629aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (k = 0; k < i; k++, r++) {
630aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (r->resp) {
631aecfc01dSrui zang - Sun Microsystems - Beijing China 			/* Clear before freeing -- maybe a password */
632aecfc01dSrui zang - Sun Microsystems - Beijing China 			bzero(r->resp, strlen(r->resp));
633aecfc01dSrui zang - Sun Microsystems - Beijing China 			free(r->resp);
634aecfc01dSrui zang - Sun Microsystems - Beijing China 			r->resp = NULL;
635aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
636aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
637aecfc01dSrui zang - Sun Microsystems - Beijing China 
638aecfc01dSrui zang - Sun Microsystems - Beijing China 	free(*response);
639aecfc01dSrui zang - Sun Microsystems - Beijing China 	*response = NULL;
640aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (PAM_CONV_ERR);
641aecfc01dSrui zang - Sun Microsystems - Beijing China }
642aecfc01dSrui zang - Sun Microsystems - Beijing China 
643aecfc01dSrui zang - Sun Microsystems - Beijing China #define	DEF_FILE	"/etc/default/login"
644aecfc01dSrui zang - Sun Microsystems - Beijing China 
645aecfc01dSrui zang - Sun Microsystems - Beijing China /* Get PASSREQ from default file */
646aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
vt_default(void)647aecfc01dSrui zang - Sun Microsystems - Beijing China vt_default(void)
648aecfc01dSrui zang - Sun Microsystems - Beijing China {
649aecfc01dSrui zang - Sun Microsystems - Beijing China 	int flags;
650aecfc01dSrui zang - Sun Microsystems - Beijing China 	char *ptr;
651aecfc01dSrui zang - Sun Microsystems - Beijing China 	boolean_t retval = B_FALSE;
652aecfc01dSrui zang - Sun Microsystems - Beijing China 
653aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((defopen(DEF_FILE)) == 0) {
654aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* ignore case */
655aecfc01dSrui zang - Sun Microsystems - Beijing China 		flags = defcntl(DC_GETFLAGS, 0);
656aecfc01dSrui zang - Sun Microsystems - Beijing China 		TURNOFF(flags, DC_CASE);
657aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) defcntl(DC_SETFLAGS, flags);
658aecfc01dSrui zang - Sun Microsystems - Beijing China 
659aecfc01dSrui zang - Sun Microsystems - Beijing China 		if ((ptr = defread("PASSREQ=")) != NULL &&
660aecfc01dSrui zang - Sun Microsystems - Beijing China 		    strcasecmp("YES", ptr) == 0)
661aecfc01dSrui zang - Sun Microsystems - Beijing China 			retval = B_TRUE;
662aecfc01dSrui zang - Sun Microsystems - Beijing China 
663aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) defopen(NULL);
664aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
665aecfc01dSrui zang - Sun Microsystems - Beijing China 
666aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (retval);
667aecfc01dSrui zang - Sun Microsystems - Beijing China }
668aecfc01dSrui zang - Sun Microsystems - Beijing China 
669aecfc01dSrui zang - Sun Microsystems - Beijing China /*
670aecfc01dSrui zang - Sun Microsystems - Beijing China  * VT_CLEAR_SCREEN_STR is the console terminal escape sequence used to
671aecfc01dSrui zang - Sun Microsystems - Beijing China  * clear the current screen.  The vt special console (/dev/vt/1) is
672aecfc01dSrui zang - Sun Microsystems - Beijing China  * just reserved for vtdaemon, and the TERM/termcap of it is always
673aecfc01dSrui zang - Sun Microsystems - Beijing China  * the local sun-color, which is always supported by our kernel terminal
674aecfc01dSrui zang - Sun Microsystems - Beijing China  * emulator.
675aecfc01dSrui zang - Sun Microsystems - Beijing China  */
676aecfc01dSrui zang - Sun Microsystems - Beijing China #define	VT_CLEAR_SCREEN_STR	"\033[2J\033[1;1H"
677aecfc01dSrui zang - Sun Microsystems - Beijing China 
678aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_do_auth(int target_vt)679aecfc01dSrui zang - Sun Microsystems - Beijing China vt_do_auth(int target_vt)
680aecfc01dSrui zang - Sun Microsystems - Beijing China {
681aecfc01dSrui zang - Sun Microsystems - Beijing China 	char	user_name[sizeof (((struct utmpx *)0)->ut_line) + 1] = {'\0'};
682aecfc01dSrui zang - Sun Microsystems - Beijing China 	pam_handle_t	*vt_pamh;
683aecfc01dSrui zang - Sun Microsystems - Beijing China 	int		err;
684aecfc01dSrui zang - Sun Microsystems - Beijing China 	int		pam_flag = 0;
685aecfc01dSrui zang - Sun Microsystems - Beijing China 	int		chpasswd_tries;
686aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct pam_conv pam_conv = {vt_conv, NULL};
687aecfc01dSrui zang - Sun Microsystems - Beijing China 	pid_t		pid;
688aecfc01dSrui zang - Sun Microsystems - Beijing China 	adt_session_data_t	*ah;
689aecfc01dSrui zang - Sun Microsystems - Beijing China 
690aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_read_utx(target_vt, &pid, user_name);
691aecfc01dSrui zang - Sun Microsystems - Beijing China 
692aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pid == (pid_t)-1 || user_name[0] == '\0')
693aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
694aecfc01dSrui zang - Sun Microsystems - Beijing China 
695aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((err = pam_start("vtdaemon", user_name, &pam_conv,
696aecfc01dSrui zang - Sun Microsystems - Beijing China 	    &vt_pamh)) != PAM_SUCCESS)
697aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
698aecfc01dSrui zang - Sun Microsystems - Beijing China 
699aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
700aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * firstly switch to the vtdaemon special console
701aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * and clear the current screen
702aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
703aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ioctl(daemonfd, VT_ACTIVATE, VT_DAEMON_ARG);
704aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) write(daemonfd, VT_CLEAR_SCREEN_STR,
705aecfc01dSrui zang - Sun Microsystems - Beijing China 	    strlen(VT_CLEAR_SCREEN_STR));
706aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ioctl(daemonfd, VT_SET_TARGET, target_vt);
707aecfc01dSrui zang - Sun Microsystems - Beijing China 
708aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_lock(&vt_mutex);
709aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_auth_doing = B_TRUE;
710aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_hotkeys_pending = B_FALSE;
711aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_unlock(&vt_mutex);
712aecfc01dSrui zang - Sun Microsystems - Beijing China 
713aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
714aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Fetch audit handle.
715aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
716aecfc01dSrui zang - Sun Microsystems - Beijing China 	ah = vt_ah_array[target_vt - 1];
717aecfc01dSrui zang - Sun Microsystems - Beijing China 
718aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_default())
719aecfc01dSrui zang - Sun Microsystems - Beijing China 		pam_flag = PAM_DISALLOW_NULL_AUTHTOK;
720aecfc01dSrui zang - Sun Microsystems - Beijing China 
721aecfc01dSrui zang - Sun Microsystems - Beijing China 	do {
722aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (VT_IS_SYSTEM_CONSOLE(target_vt))
723aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fprintf(stdout,
724aecfc01dSrui zang - Sun Microsystems - Beijing China 			    "\nUnlock user %s on the system console\n",
725aecfc01dSrui zang - Sun Microsystems - Beijing China 			    user_name);
726aecfc01dSrui zang - Sun Microsystems - Beijing China 		else
727aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fprintf(stdout,
728aecfc01dSrui zang - Sun Microsystems - Beijing China 			    "\nUnlock user %s on vt/%d\n", user_name,
729aecfc01dSrui zang - Sun Microsystems - Beijing China 			    target_vt);
730aecfc01dSrui zang - Sun Microsystems - Beijing China 
731aecfc01dSrui zang - Sun Microsystems - Beijing China 		err = pam_authenticate(vt_pamh, pam_flag);
732aecfc01dSrui zang - Sun Microsystems - Beijing China 
733aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) mutex_lock(&vt_mutex);
734aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (vt_hotkeys_pending) {
735aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) mutex_unlock(&vt_mutex);
736aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
737aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
738aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) mutex_unlock(&vt_mutex);
739aecfc01dSrui zang - Sun Microsystems - Beijing China 
740aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (err == PAM_SUCCESS) {
741aecfc01dSrui zang - Sun Microsystems - Beijing China 			err = pam_acct_mgmt(vt_pamh, pam_flag);
742aecfc01dSrui zang - Sun Microsystems - Beijing China 
743aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) mutex_lock(&vt_mutex);
744aecfc01dSrui zang - Sun Microsystems - Beijing China 			if (vt_hotkeys_pending) {
745aecfc01dSrui zang - Sun Microsystems - Beijing China 				(void) mutex_unlock(&vt_mutex);
746aecfc01dSrui zang - Sun Microsystems - Beijing China 				break;
747aecfc01dSrui zang - Sun Microsystems - Beijing China 			}
748aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) mutex_unlock(&vt_mutex);
749aecfc01dSrui zang - Sun Microsystems - Beijing China 
750aecfc01dSrui zang - Sun Microsystems - Beijing China 			if (err == PAM_NEW_AUTHTOK_REQD) {
751aecfc01dSrui zang - Sun Microsystems - Beijing China 				chpasswd_tries = 0;
752aecfc01dSrui zang - Sun Microsystems - Beijing China 
753aecfc01dSrui zang - Sun Microsystems - Beijing China 				do {
754aecfc01dSrui zang - Sun Microsystems - Beijing China 					err = pam_chauthtok(vt_pamh,
755aecfc01dSrui zang - Sun Microsystems - Beijing China 					    PAM_CHANGE_EXPIRED_AUTHTOK);
756aecfc01dSrui zang - Sun Microsystems - Beijing China 					chpasswd_tries++;
757aecfc01dSrui zang - Sun Microsystems - Beijing China 
758aecfc01dSrui zang - Sun Microsystems - Beijing China 					(void) mutex_lock(&vt_mutex);
759aecfc01dSrui zang - Sun Microsystems - Beijing China 					if (vt_hotkeys_pending) {
760aecfc01dSrui zang - Sun Microsystems - Beijing China 						(void) mutex_unlock(&vt_mutex);
761aecfc01dSrui zang - Sun Microsystems - Beijing China 						break;
762aecfc01dSrui zang - Sun Microsystems - Beijing China 					}
763aecfc01dSrui zang - Sun Microsystems - Beijing China 					(void) mutex_unlock(&vt_mutex);
764aecfc01dSrui zang - Sun Microsystems - Beijing China 
765aecfc01dSrui zang - Sun Microsystems - Beijing China 				} while ((err == PAM_AUTHTOK_ERR ||
766aecfc01dSrui zang - Sun Microsystems - Beijing China 				    err == PAM_TRY_AGAIN) &&
767aecfc01dSrui zang - Sun Microsystems - Beijing China 				    chpasswd_tries < DEF_ATTEMPTS);
768aecfc01dSrui zang - Sun Microsystems - Beijing China 
769aecfc01dSrui zang - Sun Microsystems - Beijing China 				(void) mutex_lock(&vt_mutex);
770aecfc01dSrui zang - Sun Microsystems - Beijing China 				if (vt_hotkeys_pending) {
771aecfc01dSrui zang - Sun Microsystems - Beijing China 					(void) mutex_unlock(&vt_mutex);
772aecfc01dSrui zang - Sun Microsystems - Beijing China 					break;
773aecfc01dSrui zang - Sun Microsystems - Beijing China 				}
774aecfc01dSrui zang - Sun Microsystems - Beijing China 				(void) mutex_unlock(&vt_mutex);
775aecfc01dSrui zang - Sun Microsystems - Beijing China 
776aecfc01dSrui zang - Sun Microsystems - Beijing China 				vt_audit_event(ah, ADT_passwd, err);
777aecfc01dSrui zang - Sun Microsystems - Beijing China 			}
778aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
779aecfc01dSrui zang - Sun Microsystems - Beijing China 
780aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
781aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Only audit failed unlock here, successful unlock
782aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * will be audited after switching to target vt.
783aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
784aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (err != PAM_SUCCESS) {
785aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) fprintf(stdout, "%s",
786aecfc01dSrui zang - Sun Microsystems - Beijing China 			    pam_strerror(vt_pamh, err));
787aecfc01dSrui zang - Sun Microsystems - Beijing China 
788aecfc01dSrui zang - Sun Microsystems - Beijing China 			vt_audit_event(ah, ADT_screenunlock, err);
789aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
790aecfc01dSrui zang - Sun Microsystems - Beijing China 
791aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) mutex_lock(&vt_mutex);
792aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (vt_hotkeys_pending) {
793aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) mutex_unlock(&vt_mutex);
794aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
795aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
796aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) mutex_unlock(&vt_mutex);
797aecfc01dSrui zang - Sun Microsystems - Beijing China 
798aecfc01dSrui zang - Sun Microsystems - Beijing China 	} while (err != PAM_SUCCESS);
799aecfc01dSrui zang - Sun Microsystems - Beijing China 
800aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_lock(&vt_mutex);
801aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!vt_hotkeys_pending) {
802aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
803aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Should be PAM_SUCCESS to reach here.
804aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
805aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ioctl(daemonfd, VT_ACTIVATE, target_vt);
806aecfc01dSrui zang - Sun Microsystems - Beijing China 
807aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_audit_event(ah, ADT_screenunlock, err);
808aecfc01dSrui zang - Sun Microsystems - Beijing China 
809aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
810aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Free audit handle.
811aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
812aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) adt_end_session(ah);
813aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_ah_array[target_vt - 1] = NULL;
814aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
815aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_unlock(&vt_mutex);
816aecfc01dSrui zang - Sun Microsystems - Beijing China 
817aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) pam_end(vt_pamh, err);
818aecfc01dSrui zang - Sun Microsystems - Beijing China 
819aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_lock(&vt_mutex);
820aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_auth_doing = B_FALSE;
821aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_clear_events();
822aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_unlock(&vt_mutex);
823aecfc01dSrui zang - Sun Microsystems - Beijing China }
824aecfc01dSrui zang - Sun Microsystems - Beijing China 
825aecfc01dSrui zang - Sun Microsystems - Beijing China /* main thread (lock and auth) */
826ea272279Srui zang - Sun Microsystems - Beijing China static void __NORETURN
vt_serve_events(void)827aecfc01dSrui zang - Sun Microsystems - Beijing China vt_serve_events(void)
828aecfc01dSrui zang - Sun Microsystems - Beijing China {
829aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct pollfd pollfds[1];
830aecfc01dSrui zang - Sun Microsystems - Beijing China 	int ret;
831aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_evt_t ve;
832aecfc01dSrui zang - Sun Microsystems - Beijing China 
833aecfc01dSrui zang - Sun Microsystems - Beijing China 	pollfds[0].fd = eventstream[1];
834aecfc01dSrui zang - Sun Microsystems - Beijing China 	pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI;
835aecfc01dSrui zang - Sun Microsystems - Beijing China 
836aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (;;) {
837aecfc01dSrui zang - Sun Microsystems - Beijing China 		pollfds[0].revents = 0;
838aecfc01dSrui zang - Sun Microsystems - Beijing China 		ret = poll(pollfds,
839aecfc01dSrui zang - Sun Microsystems - Beijing China 		    sizeof (pollfds) / sizeof (struct pollfd), -1);
840aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (ret == -1 && errno == EINTR) {
841aecfc01dSrui zang - Sun Microsystems - Beijing China 			continue;
842aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
843aecfc01dSrui zang - Sun Microsystems - Beijing China 
844aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (pollfds[0].revents && eventstream_read(1, &ve)) {
845aecfc01dSrui zang - Sun Microsystems - Beijing China 			/* new request */
846aecfc01dSrui zang - Sun Microsystems - Beijing China 			switch (ve.ve_cmd) {
847aecfc01dSrui zang - Sun Microsystems - Beijing China 			case VT_EV_AUTH:
848aecfc01dSrui zang - Sun Microsystems - Beijing China 				vt_do_auth(ve.ve_info);
849aecfc01dSrui zang - Sun Microsystems - Beijing China 				break;
850aecfc01dSrui zang - Sun Microsystems - Beijing China 
851aecfc01dSrui zang - Sun Microsystems - Beijing China 			case VT_EV_LOCK:
852aecfc01dSrui zang - Sun Microsystems - Beijing China 				vt_activate_screenlock(ve.ve_info);
853aecfc01dSrui zang - Sun Microsystems - Beijing China 				break;
854aecfc01dSrui zang - Sun Microsystems - Beijing China 
855aecfc01dSrui zang - Sun Microsystems - Beijing China 			case VT_EV_ACTIVATE:
856aecfc01dSrui zang - Sun Microsystems - Beijing China 				/* directly activate target vt */
857aecfc01dSrui zang - Sun Microsystems - Beijing China 				vt_do_activate(ve.ve_info);
858aecfc01dSrui zang - Sun Microsystems - Beijing China 				break;
859aecfc01dSrui zang - Sun Microsystems - Beijing China 			}
860aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
861aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
862aecfc01dSrui zang - Sun Microsystems - Beijing China }
863aecfc01dSrui zang - Sun Microsystems - Beijing China 
864aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_check_target_session(uint32_t target_vt)865aecfc01dSrui zang - Sun Microsystems - Beijing China vt_check_target_session(uint32_t target_vt)
866aecfc01dSrui zang - Sun Microsystems - Beijing China {
867aecfc01dSrui zang - Sun Microsystems - Beijing China 	pid_t	pid = (pid_t)-1;
868aecfc01dSrui zang - Sun Microsystems - Beijing China 
869aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!vt_secure) {
870aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_ev_request(VT_EV_ACTIVATE, target_vt);
871aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
872aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
873aecfc01dSrui zang - Sun Microsystems - Beijing China 
874aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* check the target session */
875aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_read_utx(target_vt, &pid, NULL);
876aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pid  == (pid_t)-1) {
877aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_ev_request(VT_EV_ACTIVATE, target_vt);
878aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
879aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
880aecfc01dSrui zang - Sun Microsystems - Beijing China 
881aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_ev_request(VT_EV_AUTH, target_vt);
882aecfc01dSrui zang - Sun Microsystems - Beijing China }
883aecfc01dSrui zang - Sun Microsystems - Beijing China 
884aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
vt_get_active_disp_info(struct vt_dispinfo * vd)885aecfc01dSrui zang - Sun Microsystems - Beijing China vt_get_active_disp_info(struct vt_dispinfo *vd)
886aecfc01dSrui zang - Sun Microsystems - Beijing China {
887aecfc01dSrui zang - Sun Microsystems - Beijing China 	int fd;
888aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vt_stat state;
889aecfc01dSrui zang - Sun Microsystems - Beijing China 	char vtname[16];
890aecfc01dSrui zang - Sun Microsystems - Beijing China 
891aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_RDONLY)) < 0)
892aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
893aecfc01dSrui zang - Sun Microsystems - Beijing China 
894aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ioctl(fd, VT_GETSTATE, &state) != 0) {
895aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) close(fd);
896aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
897aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
898aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) close(fd);
899aecfc01dSrui zang - Sun Microsystems - Beijing China 
900aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) snprintf(vtname, sizeof (vtname), "/dev/vt/%d", state.v_active);
901aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((fd = open(vtname, O_RDONLY)) < 0)
902aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
903aecfc01dSrui zang - Sun Microsystems - Beijing China 
904aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ioctl(fd, VT_GETDISPINFO, vd) != 0) {
905aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) close(fd);
906aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
907aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
908aecfc01dSrui zang - Sun Microsystems - Beijing China 
909aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) close(fd);
910aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (B_TRUE);
911aecfc01dSrui zang - Sun Microsystems - Beijing China }
912aecfc01dSrui zang - Sun Microsystems - Beijing China 
913aecfc01dSrui zang - Sun Microsystems - Beijing China /*
914aecfc01dSrui zang - Sun Microsystems - Beijing China  * Xserver registers its pid into kernel to associate it with
915aecfc01dSrui zang - Sun Microsystems - Beijing China  * its vt upon startup for each graphical display. So here we can
916aecfc01dSrui zang - Sun Microsystems - Beijing China  * check if the pid is of the Xserver for the current active
917aecfc01dSrui zang - Sun Microsystems - Beijing China  * display when we receive a special VT_EV_X_EXIT request from
918aecfc01dSrui zang - Sun Microsystems - Beijing China  * a process. If the request does not come from the current
919aecfc01dSrui zang - Sun Microsystems - Beijing China  * active Xserver, it is discarded.
920aecfc01dSrui zang - Sun Microsystems - Beijing China  */
921aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
vt_check_disp_active(pid_t x_pid)922aecfc01dSrui zang - Sun Microsystems - Beijing China vt_check_disp_active(pid_t x_pid)
923aecfc01dSrui zang - Sun Microsystems - Beijing China {
924aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vt_dispinfo vd;
925aecfc01dSrui zang - Sun Microsystems - Beijing China 
926aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_get_active_disp_info(&vd) &&
927aecfc01dSrui zang - Sun Microsystems - Beijing China 	    vd.v_pid == x_pid)
928aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_TRUE);
929aecfc01dSrui zang - Sun Microsystems - Beijing China 
930aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (B_FALSE);
931aecfc01dSrui zang - Sun Microsystems - Beijing China }
932aecfc01dSrui zang - Sun Microsystems - Beijing China 
933aecfc01dSrui zang - Sun Microsystems - Beijing China /*
934aecfc01dSrui zang - Sun Microsystems - Beijing China  * check if the pid is of the Xserver for the current active display,
935aecfc01dSrui zang - Sun Microsystems - Beijing China  * return true when it is, and then also return other associated
936aecfc01dSrui zang - Sun Microsystems - Beijing China  * information with the Xserver.
937aecfc01dSrui zang - Sun Microsystems - Beijing China  */
938aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
vt_get_disp_info(pid_t x_pid,int * logged_in,int * display_num)939aecfc01dSrui zang - Sun Microsystems - Beijing China vt_get_disp_info(pid_t x_pid, int *logged_in, int *display_num)
940aecfc01dSrui zang - Sun Microsystems - Beijing China {
941aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vt_dispinfo vd;
942aecfc01dSrui zang - Sun Microsystems - Beijing China 
943aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!vt_get_active_disp_info(&vd) ||
944aecfc01dSrui zang - Sun Microsystems - Beijing China 	    vd.v_pid != x_pid)
945aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
946aecfc01dSrui zang - Sun Microsystems - Beijing China 
947aecfc01dSrui zang - Sun Microsystems - Beijing China 	*logged_in = vd.v_login;
948aecfc01dSrui zang - Sun Microsystems - Beijing China 	*display_num = vd.v_dispnum;
949aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (B_TRUE);
950aecfc01dSrui zang - Sun Microsystems - Beijing China }
951aecfc01dSrui zang - Sun Microsystems - Beijing China 
952aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_terminate_auth(void)953aecfc01dSrui zang - Sun Microsystems - Beijing China vt_terminate_auth(void)
954aecfc01dSrui zang - Sun Microsystems - Beijing China {
955aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct timespec sleeptime;
956aecfc01dSrui zang - Sun Microsystems - Beijing China 
957aecfc01dSrui zang - Sun Microsystems - Beijing China 	sleeptime.tv_sec = 0;
958aecfc01dSrui zang - Sun Microsystems - Beijing China 	sleeptime.tv_nsec = 1000000; /* 1ms */
959aecfc01dSrui zang - Sun Microsystems - Beijing China 
960aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_lock(&vt_mutex);
961aecfc01dSrui zang - Sun Microsystems - Beijing China 	while (vt_auth_doing) {
962aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_ev_request(VT_EV_TERMINATE_AUTH, 0);
963aecfc01dSrui zang - Sun Microsystems - Beijing China 
964aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (vt_auth_doing) {
965aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) mutex_unlock(&vt_mutex);
966aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) nanosleep(&sleeptime, NULL);
967aecfc01dSrui zang - Sun Microsystems - Beijing China 			sleeptime.tv_nsec *= 2;
968aecfc01dSrui zang - Sun Microsystems - Beijing China 			(void) mutex_lock(&vt_mutex);
969aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
970aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
971aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_unlock(&vt_mutex);
972aecfc01dSrui zang - Sun Microsystems - Beijing China }
973aecfc01dSrui zang - Sun Microsystems - Beijing China 
974aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_do_hotkeys(pid_t pid,uint32_t target_vt)975aecfc01dSrui zang - Sun Microsystems - Beijing China vt_do_hotkeys(pid_t pid, uint32_t target_vt)
976aecfc01dSrui zang - Sun Microsystems - Beijing China {
977aecfc01dSrui zang - Sun Microsystems - Beijing China 	int		logged_in;
978aecfc01dSrui zang - Sun Microsystems - Beijing China 	int		display_num;
979aecfc01dSrui zang - Sun Microsystems - Beijing China 
980aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (validate_target_vt(target_vt) != 0)
981aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
982aecfc01dSrui zang - Sun Microsystems - Beijing China 
983aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
984aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Maybe last switch action is being taken and the lock is ongoing,
985aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * here we must reject the newly request.
986aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
987aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_lock(&vt_mutex);
988aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_hotkeys_pending) {
989aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) mutex_unlock(&vt_mutex);
990aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
991aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
992aecfc01dSrui zang - Sun Microsystems - Beijing China 
993aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* cleared in vt_do_active and vt_do_auth */
994aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_hotkeys_pending = B_TRUE;
995aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) mutex_unlock(&vt_mutex);
996aecfc01dSrui zang - Sun Microsystems - Beijing China 
997aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_terminate_auth();
998aecfc01dSrui zang - Sun Microsystems - Beijing China 
999aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* check source session for this hotkeys request */
1000aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pid == 0) {
1001aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* ok, it comes from kernel. */
1002aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (vt_secure)
1003aecfc01dSrui zang - Sun Microsystems - Beijing China 			vt_check_source_audit();
1004aecfc01dSrui zang - Sun Microsystems - Beijing China 
1005aecfc01dSrui zang - Sun Microsystems - Beijing China 		/* then only need to check target session */
1006aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_check_target_session(target_vt);
1007aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1008aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1009aecfc01dSrui zang - Sun Microsystems - Beijing China 
1010aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
1011aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * check if it comes from current active X graphical session,
1012aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * if not, ignore this request.
1013aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
1014aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!vt_get_disp_info(pid, &logged_in, &display_num)) {
1015aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) mutex_lock(&vt_mutex);
1016aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_hotkeys_pending = B_FALSE;
1017aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) mutex_unlock(&vt_mutex);
1018aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1019aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1020aecfc01dSrui zang - Sun Microsystems - Beijing China 
1021aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (logged_in && vt_secure)
1022aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_ev_request(VT_EV_LOCK, display_num);
1023aecfc01dSrui zang - Sun Microsystems - Beijing China 
1024aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_check_target_session(target_vt);
1025aecfc01dSrui zang - Sun Microsystems - Beijing China }
1026aecfc01dSrui zang - Sun Microsystems - Beijing China 
1027aecfc01dSrui zang - Sun Microsystems - Beijing China /*
1028aecfc01dSrui zang - Sun Microsystems - Beijing China  * The main routine for the door server that deals with secure hotkeys
1029aecfc01dSrui zang - Sun Microsystems - Beijing China  */
1030aecfc01dSrui zang - Sun Microsystems - Beijing China /* ARGSUSED */
1031aecfc01dSrui zang - Sun Microsystems - Beijing China static void
server_for_door(void * cookie,char * args,size_t alen,door_desc_t * dp,uint_t n_desc)1032aecfc01dSrui zang - Sun Microsystems - Beijing China server_for_door(void *cookie, char *args, size_t alen, door_desc_t *dp,
1033aecfc01dSrui zang - Sun Microsystems - Beijing China     uint_t n_desc)
1034aecfc01dSrui zang - Sun Microsystems - Beijing China {
1035aecfc01dSrui zang - Sun Microsystems - Beijing China 	ucred_t *uc = NULL;
1036aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_cmd_arg_t *vtargp;
1037aecfc01dSrui zang - Sun Microsystems - Beijing China 
1038aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* LINTED E_BAD_PTR_CAST_ALIGN */
1039aecfc01dSrui zang - Sun Microsystems - Beijing China 	vtargp = (vt_cmd_arg_t *)args;
1040aecfc01dSrui zang - Sun Microsystems - Beijing China 
1041aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vtargp == NULL ||
1042aecfc01dSrui zang - Sun Microsystems - Beijing China 	    alen != sizeof (vt_cmd_arg_t) ||
1043aecfc01dSrui zang - Sun Microsystems - Beijing China 	    door_ucred(&uc) != 0) {
1044aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) door_return(NULL, 0, NULL, 0);
1045aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1046aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1047aecfc01dSrui zang - Sun Microsystems - Beijing China 
1048aecfc01dSrui zang - Sun Microsystems - Beijing China 	switch (vtargp->vt_ev) {
1049aecfc01dSrui zang - Sun Microsystems - Beijing China 	case VT_EV_X_EXIT:
1050aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
1051aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Xserver will issue this event requesting to switch back
1052aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * to previous active vt when it's exiting and the associated
1053aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * vt is currently active.
1054aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
1055aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (vt_check_disp_active(ucred_getpid(uc)))
1056aecfc01dSrui zang - Sun Microsystems - Beijing China 			vt_do_hotkeys(0, vtargp->vt_num);
1057aecfc01dSrui zang - Sun Microsystems - Beijing China 		break;
1058aecfc01dSrui zang - Sun Microsystems - Beijing China 
1059aecfc01dSrui zang - Sun Microsystems - Beijing China 	case VT_EV_HOTKEYS:
1060aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (!vt_hotkeys)	/* hotkeys are disabled? */
1061aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
1062aecfc01dSrui zang - Sun Microsystems - Beijing China 
1063aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_do_hotkeys(ucred_getpid(uc), vtargp->vt_num);
1064aecfc01dSrui zang - Sun Microsystems - Beijing China 		break;
1065aecfc01dSrui zang - Sun Microsystems - Beijing China 
1066aecfc01dSrui zang - Sun Microsystems - Beijing China 	default:
1067aecfc01dSrui zang - Sun Microsystems - Beijing China 		break;
1068aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1069aecfc01dSrui zang - Sun Microsystems - Beijing China 
1070aecfc01dSrui zang - Sun Microsystems - Beijing China 	ucred_free(uc);
1071aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) door_return(NULL, 0, NULL, 0);
1072aecfc01dSrui zang - Sun Microsystems - Beijing China }
1073aecfc01dSrui zang - Sun Microsystems - Beijing China 
1074aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
setup_door(void)1075aecfc01dSrui zang - Sun Microsystems - Beijing China setup_door(void)
1076aecfc01dSrui zang - Sun Microsystems - Beijing China {
1077aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((vt_door = door_create(server_for_door, NULL,
1078aecfc01dSrui zang - Sun Microsystems - Beijing China 	    DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) < 0) {
1079aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "door_create failed: %s", strerror(errno));
1080aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
1081aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1082aecfc01dSrui zang - Sun Microsystems - Beijing China 
1083aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) fdetach(vt_door_path);
1084aecfc01dSrui zang - Sun Microsystems - Beijing China 
1085aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (fattach(vt_door, vt_door_path) != 0) {
1086aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "fattach to %s failed: %s",
1087aecfc01dSrui zang - Sun Microsystems - Beijing China 		    vt_door_path, strerror(errno));
1088aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) door_revoke(vt_door);
1089aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) fdetach(vt_door_path);
1090aecfc01dSrui zang - Sun Microsystems - Beijing China 		vt_door = -1;
1091aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
1092aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1093aecfc01dSrui zang - Sun Microsystems - Beijing China 
1094aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (B_TRUE);
1095aecfc01dSrui zang - Sun Microsystems - Beijing China }
1096aecfc01dSrui zang - Sun Microsystems - Beijing China 
1097aecfc01dSrui zang - Sun Microsystems - Beijing China /*
1098aecfc01dSrui zang - Sun Microsystems - Beijing China  * check to see if vtdaemon is already running.
1099aecfc01dSrui zang - Sun Microsystems - Beijing China  *
1100aecfc01dSrui zang - Sun Microsystems - Beijing China  * The idea here is that we want to open the path to which we will
1101aecfc01dSrui zang - Sun Microsystems - Beijing China  * attach our door, lock it, and then make sure that no-one has beat us
1102aecfc01dSrui zang - Sun Microsystems - Beijing China  * to fattach(3c)ing onto it.
1103aecfc01dSrui zang - Sun Microsystems - Beijing China  *
1104aecfc01dSrui zang - Sun Microsystems - Beijing China  * fattach(3c) is really a mount, so there are actually two possible
1105aecfc01dSrui zang - Sun Microsystems - Beijing China  * vnodes we could be dealing with.  Our strategy is as follows:
1106aecfc01dSrui zang - Sun Microsystems - Beijing China  *
1107aecfc01dSrui zang - Sun Microsystems - Beijing China  * - If the file we opened is a regular file (common case):
1108aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	There is no fattach(3c)ed door, so we have a chance of becoming
1109aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	the running vtdaemon. We attempt to lock the file: if it is
1110aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	already locked, that means someone else raced us here, so we
1111aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	lose and give up.
1112aecfc01dSrui zang - Sun Microsystems - Beijing China  *
1113aecfc01dSrui zang - Sun Microsystems - Beijing China  * - If the file we opened is a namefs file:
1114aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	This means there is already an established door fattach(3c)'ed
1115aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	to the rendezvous path.  We've lost the race, so we give up.
1116aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	Note that in this case we also try to grab the file lock, and
1117aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	will succeed in acquiring it since the vnode locked by the
1118aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	"winning" vtdaemon was a regular one, and the one we locked was
1119aecfc01dSrui zang - Sun Microsystems - Beijing China  * 	the fattach(3c)'ed door node.  At any rate, no harm is done.
1120aecfc01dSrui zang - Sun Microsystems - Beijing China  */
1121aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
make_daemon_exclusive(void)1122aecfc01dSrui zang - Sun Microsystems - Beijing China make_daemon_exclusive(void)
1123aecfc01dSrui zang - Sun Microsystems - Beijing China {
1124aecfc01dSrui zang - Sun Microsystems - Beijing China 	int doorfd = -1;
1125aecfc01dSrui zang - Sun Microsystems - Beijing China 	boolean_t ret = B_FALSE;
1126aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct stat st;
1127aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct flock flock;
1128aecfc01dSrui zang - Sun Microsystems - Beijing China 
1129aecfc01dSrui zang - Sun Microsystems - Beijing China top:
1130aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((doorfd = open(vt_door_path, O_CREAT|O_RDWR,
1131aecfc01dSrui zang - Sun Microsystems - Beijing China 	    S_IREAD|S_IWRITE|S_IRGRP|S_IROTH)) < 0) {
1132aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "failed to open %s", vt_door_path);
1133aecfc01dSrui zang - Sun Microsystems - Beijing China 		goto out;
1134aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1135aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (fstat(doorfd, &st) < 0) {
1136aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "failed to stat %s", vt_door_path);
1137aecfc01dSrui zang - Sun Microsystems - Beijing China 		goto out;
1138aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1139aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
1140aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Lock the file to synchronize
1141aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
1142aecfc01dSrui zang - Sun Microsystems - Beijing China 	flock.l_type = F_WRLCK;
1143aecfc01dSrui zang - Sun Microsystems - Beijing China 	flock.l_whence = SEEK_SET;
1144aecfc01dSrui zang - Sun Microsystems - Beijing China 	flock.l_start = (off_t)0;
1145aecfc01dSrui zang - Sun Microsystems - Beijing China 	flock.l_len = (off_t)0;
1146aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (fcntl(doorfd, F_SETLK, &flock) < 0) {
1147aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
1148aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Someone else raced us here and grabbed the lock file
1149aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * first.  A warning here and exit.
1150aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
1151aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "vtdaemon is already running!");
1152aecfc01dSrui zang - Sun Microsystems - Beijing China 		goto out;
1153aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1154aecfc01dSrui zang - Sun Microsystems - Beijing China 
1155aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (strcmp(st.st_fstype, "namefs") == 0) {
1156aecfc01dSrui zang - Sun Microsystems - Beijing China 		struct door_info info;
1157aecfc01dSrui zang - Sun Microsystems - Beijing China 
1158aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
1159aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * There is already something fattach()'ed to this file.
1160aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * Lets see what the door is up to.
1161aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
1162aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (door_info(doorfd, &info) == 0 && info.di_target != -1) {
1163aecfc01dSrui zang - Sun Microsystems - Beijing China 			syslog(LOG_ERR, "vtdaemon is already running!");
1164aecfc01dSrui zang - Sun Microsystems - Beijing China 			goto out;
1165aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
1166aecfc01dSrui zang - Sun Microsystems - Beijing China 
1167aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) fdetach(vt_door_path);
1168aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) close(doorfd);
1169aecfc01dSrui zang - Sun Microsystems - Beijing China 		goto top;
1170aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1171aecfc01dSrui zang - Sun Microsystems - Beijing China 
1172aecfc01dSrui zang - Sun Microsystems - Beijing China 	ret = setup_door();
1173aecfc01dSrui zang - Sun Microsystems - Beijing China 
1174aecfc01dSrui zang - Sun Microsystems - Beijing China out:
1175aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) close(doorfd);
1176aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (ret);
1177aecfc01dSrui zang - Sun Microsystems - Beijing China }
1178aecfc01dSrui zang - Sun Microsystems - Beijing China 
1179aecfc01dSrui zang - Sun Microsystems - Beijing China static boolean_t
mkvtdir(void)1180aecfc01dSrui zang - Sun Microsystems - Beijing China mkvtdir(void)
1181aecfc01dSrui zang - Sun Microsystems - Beijing China {
1182aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct stat st;
1183aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
1184aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * We must create and lock everyone but root out of VT_TMPDIR
1185aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * since anyone can open any UNIX domain socket, regardless of
1186aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * its file system permissions.
1187aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
1188aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (mkdir(VT_TMPDIR, S_IRWXU|S_IROTH|S_IXOTH|S_IRGRP|S_IXGRP) < 0 &&
1189aecfc01dSrui zang - Sun Microsystems - Beijing China 	    errno != EEXIST) {
1190aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "could not mkdir '%s'", VT_TMPDIR);
1191aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
1192aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1193aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* paranoia */
1194aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((stat(VT_TMPDIR, &st) < 0) || !S_ISDIR(st.st_mode)) {
1195aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "'%s' is not a directory", VT_TMPDIR);
1196aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (B_FALSE);
1197aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1198aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) chmod(VT_TMPDIR, S_IRWXU|S_IROTH|S_IXOTH|S_IRGRP|S_IXGRP);
1199aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (B_TRUE);
1200aecfc01dSrui zang - Sun Microsystems - Beijing China }
1201aecfc01dSrui zang - Sun Microsystems - Beijing China 
1202aecfc01dSrui zang - Sun Microsystems - Beijing China int
main(int argc,char * argv[])1203aecfc01dSrui zang - Sun Microsystems - Beijing China main(int argc, char *argv[])
1204aecfc01dSrui zang - Sun Microsystems - Beijing China {
1205aecfc01dSrui zang - Sun Microsystems - Beijing China 	int i;
1206aecfc01dSrui zang - Sun Microsystems - Beijing China 	int opt;
1207aecfc01dSrui zang - Sun Microsystems - Beijing China 	priv_set_t *privset;
1208aecfc01dSrui zang - Sun Microsystems - Beijing China 	int active;
1209aecfc01dSrui zang - Sun Microsystems - Beijing China 
1210aecfc01dSrui zang - Sun Microsystems - Beijing China 	openlog("vtdaemon", LOG_PID | LOG_CONS, 0);
1211aecfc01dSrui zang - Sun Microsystems - Beijing China 
1212aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
1213aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * Check that we have all privileges.  It would be nice to pare
1214aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * this down, but this is at least a first cut.
1215aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
1216aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((privset = priv_allocset()) == NULL) {
1217aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "priv_allocset failed");
1218aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1219aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1220aecfc01dSrui zang - Sun Microsystems - Beijing China 
1221aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (getppriv(PRIV_EFFECTIVE, privset) != 0) {
1222aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "getppriv failed", "getppriv");
1223aecfc01dSrui zang - Sun Microsystems - Beijing China 		priv_freeset(privset);
1224aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1225aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1226aecfc01dSrui zang - Sun Microsystems - Beijing China 
1227aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (priv_isfullset(privset) == B_FALSE) {
1228aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "You lack sufficient privilege "
1229aecfc01dSrui zang - Sun Microsystems - Beijing China 		    "to run this command (all privs required)");
1230aecfc01dSrui zang - Sun Microsystems - Beijing China 		priv_freeset(privset);
1231aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1232aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1233aecfc01dSrui zang - Sun Microsystems - Beijing China 	priv_freeset(privset);
1234aecfc01dSrui zang - Sun Microsystems - Beijing China 
1235aecfc01dSrui zang - Sun Microsystems - Beijing China 	while ((opt = getopt(argc, argv, "ksrc:")) != EOF) {
1236aecfc01dSrui zang - Sun Microsystems - Beijing China 		switch (opt) {
1237aecfc01dSrui zang - Sun Microsystems - Beijing China 		case 'k':
1238aecfc01dSrui zang - Sun Microsystems - Beijing China 			vt_hotkeys = B_FALSE;
1239aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
1240aecfc01dSrui zang - Sun Microsystems - Beijing China 		case 's':
1241aecfc01dSrui zang - Sun Microsystems - Beijing China 			vt_secure = B_FALSE;
1242aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
1243aecfc01dSrui zang - Sun Microsystems - Beijing China 		case 'c':
1244aecfc01dSrui zang - Sun Microsystems - Beijing China 			vtnodecount = atoi(optarg);
1245aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
1246aecfc01dSrui zang - Sun Microsystems - Beijing China 		default:
1247aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
1248aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
1249aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1250aecfc01dSrui zang - Sun Microsystems - Beijing China 
1251aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) vt_setup_signal(SIGINT, 1);
1252aecfc01dSrui zang - Sun Microsystems - Beijing China 
1253aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!mkvtdir())
1254aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1255aecfc01dSrui zang - Sun Microsystems - Beijing China 
1256aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!eventstream_init())
1257aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1258aecfc01dSrui zang - Sun Microsystems - Beijing China 
1259aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) snprintf(vt_door_path, sizeof (vt_door_path),
1260aecfc01dSrui zang - Sun Microsystems - Beijing China 	    VT_TMPDIR "/vtdaemon_door");
1261aecfc01dSrui zang - Sun Microsystems - Beijing China 
1262aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (!make_daemon_exclusive())
1263aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1264aecfc01dSrui zang - Sun Microsystems - Beijing China 
1265aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* only the main thread accepts SIGINT */
1266aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) vt_setup_signal(SIGINT, 0);
1267aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) sigset(SIGPIPE, SIG_IGN);
1268aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) signal(SIGQUIT, SIG_IGN);
1269aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) signal(SIGINT, catch);
1270aecfc01dSrui zang - Sun Microsystems - Beijing China 
1271aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (i = 0; i < 3; i++)
1272aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) close(i);
1273aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) setsid();
1274aecfc01dSrui zang - Sun Microsystems - Beijing China 
1275aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((daemonfd = open(VT_DAEMON_CONSOLE_FILE, O_RDWR)) < 0) {
1276aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1277aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1278aecfc01dSrui zang - Sun Microsystems - Beijing China 
1279aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (daemonfd != 0)
1280aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) dup2(daemonfd, STDIN_FILENO);
1281aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (daemonfd != 1)
1282aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) dup2(daemonfd, STDOUT_FILENO);
1283aecfc01dSrui zang - Sun Microsystems - Beijing China 
1284aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vtnodecount >= 2)
1285aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) ioctl(daemonfd, VT_CONFIG, vtnodecount);
1286aecfc01dSrui zang - Sun Microsystems - Beijing China 
1287aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((vt_ah_array = calloc(vtnodecount - 1,
1288aecfc01dSrui zang - Sun Microsystems - Beijing China 	    sizeof (adt_session_data_t *))) == NULL)
1289aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (1);
1290aecfc01dSrui zang - Sun Microsystems - Beijing China 
1291aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) ioctl(daemonfd, VT_GETACTIVE, &active);
1292aecfc01dSrui zang - Sun Microsystems - Beijing China 
1293aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (active == 1) {
1294aecfc01dSrui zang - Sun Microsystems - Beijing China 		/*
1295aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * This is for someone who restarts vtdaemon while vtdaemon
1296aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * is doing authentication on /dev/vt/1.
1297aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * A better way is to continue the authentication, but there
1298aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * are chances that the status of the target VT has changed.
1299aecfc01dSrui zang - Sun Microsystems - Beijing China 		 * So we just clear the screen here.
1300aecfc01dSrui zang - Sun Microsystems - Beijing China 		 */
1301aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) write(daemonfd, VT_CLEAR_SCREEN_STR,
1302aecfc01dSrui zang - Sun Microsystems - Beijing China 		    strlen(VT_CLEAR_SCREEN_STR));
1303aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1304aecfc01dSrui zang - Sun Microsystems - Beijing China 
1305aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_serve_events();
1306aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*NOTREACHED*/
1307aecfc01dSrui zang - Sun Microsystems - Beijing China }
1308aecfc01dSrui zang - Sun Microsystems - Beijing China 
1309aecfc01dSrui zang - Sun Microsystems - Beijing China static int
vt_audit_start(adt_session_data_t ** ah,pid_t pid)1310aecfc01dSrui zang - Sun Microsystems - Beijing China vt_audit_start(adt_session_data_t **ah, pid_t pid)
1311aecfc01dSrui zang - Sun Microsystems - Beijing China {
1312aecfc01dSrui zang - Sun Microsystems - Beijing China 	ucred_t *uc;
1313aecfc01dSrui zang - Sun Microsystems - Beijing China 
1314aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (adt_start_session(ah, NULL, 0))
1315aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
1316aecfc01dSrui zang - Sun Microsystems - Beijing China 
1317aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((uc = ucred_get(pid)) == NULL) {
1318aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) adt_end_session(*ah);
1319aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
1320aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1321aecfc01dSrui zang - Sun Microsystems - Beijing China 
1322aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (adt_set_from_ucred(*ah, uc, ADT_NEW)) {
1323aecfc01dSrui zang - Sun Microsystems - Beijing China 		ucred_free(uc);
1324aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) adt_end_session(*ah);
1325aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
1326aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1327aecfc01dSrui zang - Sun Microsystems - Beijing China 
1328aecfc01dSrui zang - Sun Microsystems - Beijing China 	ucred_free(uc);
1329aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (0);
1330aecfc01dSrui zang - Sun Microsystems - Beijing China }
1331aecfc01dSrui zang - Sun Microsystems - Beijing China 
1332aecfc01dSrui zang - Sun Microsystems - Beijing China /*
1333aecfc01dSrui zang - Sun Microsystems - Beijing China  * Write audit event
1334aecfc01dSrui zang - Sun Microsystems - Beijing China  */
1335aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_audit_event(adt_session_data_t * ah,au_event_t event_id,int status)1336aecfc01dSrui zang - Sun Microsystems - Beijing China vt_audit_event(adt_session_data_t *ah, au_event_t event_id, int status)
1337aecfc01dSrui zang - Sun Microsystems - Beijing China {
1338aecfc01dSrui zang - Sun Microsystems - Beijing China 	adt_event_data_t	*event;
1339aecfc01dSrui zang - Sun Microsystems - Beijing China 
1340aecfc01dSrui zang - Sun Microsystems - Beijing China 
1341aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((event = adt_alloc_event(ah, event_id)) == NULL) {
1342aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1343aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1344aecfc01dSrui zang - Sun Microsystems - Beijing China 
1345aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) adt_put_event(event,
1346aecfc01dSrui zang - Sun Microsystems - Beijing China 	    status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAILURE,
1347aecfc01dSrui zang - Sun Microsystems - Beijing China 	    status == PAM_SUCCESS ? ADT_SUCCESS : ADT_FAIL_PAM + status);
1348aecfc01dSrui zang - Sun Microsystems - Beijing China 
1349aecfc01dSrui zang - Sun Microsystems - Beijing China 	adt_free_event(event);
1350aecfc01dSrui zang - Sun Microsystems - Beijing China }
1351aecfc01dSrui zang - Sun Microsystems - Beijing China 
1352aecfc01dSrui zang - Sun Microsystems - Beijing China static void
vt_check_source_audit(void)1353aecfc01dSrui zang - Sun Microsystems - Beijing China vt_check_source_audit(void)
1354aecfc01dSrui zang - Sun Microsystems - Beijing China {
1355aecfc01dSrui zang - Sun Microsystems - Beijing China 	int	fd;
1356aecfc01dSrui zang - Sun Microsystems - Beijing China 	int	source_vt;
1357aecfc01dSrui zang - Sun Microsystems - Beijing China 	int	real_vt;
1358aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vt_stat state;
1359aecfc01dSrui zang - Sun Microsystems - Beijing China 	pid_t	pid;
1360aecfc01dSrui zang - Sun Microsystems - Beijing China 	adt_session_data_t *ah;
1361aecfc01dSrui zang - Sun Microsystems - Beijing China 
1362aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((fd = open(VT_DAEMON_CONSOLE_FILE, O_WRONLY)) < 0)
1363aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1364aecfc01dSrui zang - Sun Microsystems - Beijing China 
1365aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ioctl(fd, VT_GETSTATE, &state) != 0 ||
1366aecfc01dSrui zang - Sun Microsystems - Beijing China 	    ioctl(fd, VT_GETACTIVE, &real_vt) != 0) {
1367aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) close(fd);
1368aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1369aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1370aecfc01dSrui zang - Sun Microsystems - Beijing China 
1371aecfc01dSrui zang - Sun Microsystems - Beijing China 	source_vt = state.v_active;	/* 1..n */
1372aecfc01dSrui zang - Sun Microsystems - Beijing China 	(void) close(fd);
1373aecfc01dSrui zang - Sun Microsystems - Beijing China 
1374aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* check if it's already locked */
1375aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (real_vt == 1)	/* vtdaemon is taking over the screen */
1376aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1377aecfc01dSrui zang - Sun Microsystems - Beijing China 
1378aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_read_utx(source_vt, &pid, NULL);
1379aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (pid == (pid_t)-1)
1380aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1381aecfc01dSrui zang - Sun Microsystems - Beijing China 
1382aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_audit_start(&ah, pid) != 0) {
1383aecfc01dSrui zang - Sun Microsystems - Beijing China 		syslog(LOG_ERR, "audit start failed ");
1384aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
1385aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
1386aecfc01dSrui zang - Sun Microsystems - Beijing China 
1387aecfc01dSrui zang - Sun Microsystems - Beijing China 	/*
1388aecfc01dSrui zang - Sun Microsystems - Beijing China 	 * In case the previous session terminated abnormally.
1389aecfc01dSrui zang - Sun Microsystems - Beijing China 	 */
1390aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_ah_array[source_vt - 1] != NULL)
1391aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) adt_end_session(vt_ah_array[source_vt - 1]);
1392aecfc01dSrui zang - Sun Microsystems - Beijing China 
1393aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_ah_array[source_vt - 1] = ah;
1394aecfc01dSrui zang - Sun Microsystems - Beijing China 
1395aecfc01dSrui zang - Sun Microsystems - Beijing China 	vt_audit_event(ah, ADT_screenlock, PAM_SUCCESS);
1396aecfc01dSrui zang - Sun Microsystems - Beijing China }
1397