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