9804 hal-set-property should support --direct option
[unleashed.git] / usr / src / cmd / power / pm_pam_conv.c
blobcef797e99027c3d48e37ff5f134accbdd2fd2e24
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * This file has all of the PAM related code for sys-suspend. It is
28 * part of it's own file, as these could be part of some bigger item
29 * that can handle generic PAM facilities (certainly the getinput()
30 * function could be in a common library). However, as that does not
31 * yet exist, we replicate it here so we can get the job done.
34 #define __EXTENSIONS__ /* to expose flockfile and friends in stdio.h */
35 #include <errno.h>
36 #include <libgen.h>
37 #include <malloc.h>
38 #include <signal.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <stropts.h>
43 #include <unistd.h>
44 #include <termio.h>
46 #include <security/pam_appl.h>
48 static int ctl_c; /* was the conversation interrupted? */
50 /* ARGSUSED 1 */
51 static void
52 interrupt(int x)
54 ctl_c = 1;
58 * getinput -- read user input from stdin abort on ^C
60 * Entry noecho == TRUE, don't echo input.
62 * Exit User's input.
63 * If interrupted, send SIGINT to caller for processing.
65 static char *
66 getinput(int noecho)
68 struct termio tty;
69 unsigned short tty_flags = 0;
70 char input[PAM_MAX_RESP_SIZE + 1];
71 int c;
72 int i = 0;
73 void (*sig)(int);
75 ctl_c = 0;
76 sig = signal(SIGINT, interrupt);
77 if (noecho) {
78 (void) ioctl(fileno(stdin), TCGETA, &tty);
79 tty_flags = tty.c_lflag;
80 tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
81 (void) ioctl(fileno(stdin), TCSETAF, &tty);
83 /* go to end, but don't overflow PAM_MAX_RESP_SIZE */
84 flockfile(stdin);
85 while (ctl_c == 0 &&
86 (c = getchar_unlocked()) != '\n' &&
87 c != '\r' &&
88 c != EOF) {
89 if (i < PAM_MAX_RESP_SIZE) {
90 input[i++] = (char)c;
93 funlockfile(stdin);
94 input[i] = '\0';
95 if (noecho) {
96 tty.c_lflag = tty_flags;
97 (void) ioctl(fileno(stdin), TCSETAW, &tty);
98 (void) fputc('\n', stdout);
100 (void) signal(SIGINT, sig);
101 if (ctl_c == 1)
102 (void) kill(getpid(), SIGINT);
104 return (strdup(input));
108 * Service modules don't clean up responses if an error is returned.
109 * Free responses here.
111 static void
112 free_resp(int num_msg, struct pam_response *pr)
114 int i;
115 struct pam_response *r = pr;
117 if (pr == NULL)
118 return;
120 for (i = 0; i < num_msg; i++, r++) {
122 if (r->resp) {
123 /* clear before freeing -- may be a password */
124 bzero(r->resp, strlen(r->resp));
125 free(r->resp);
126 r->resp = NULL;
129 free(pr);
132 /* ARGSUSED */
134 pam_tty_conv(int num_msg, struct pam_message **mess,
135 struct pam_response **resp, void *my_data)
137 struct pam_message *m = *mess;
138 struct pam_response *r = calloc(num_msg, sizeof (struct pam_response));
139 int i;
141 if (num_msg >= PAM_MAX_NUM_MSG) {
142 (void) fprintf(stderr, "too many messages %d >= %d\n",
143 num_msg, PAM_MAX_NUM_MSG);
144 free(r);
145 *resp = NULL;
146 return (PAM_CONV_ERR);
149 /* Talk it out */
150 *resp = r;
151 for (i = 0; i < num_msg; i++) {
152 int echo_off;
154 /* bad message from service module */
155 if (m->msg == NULL) {
156 (void) fprintf(stderr, "message[%d]: %d/NULL\n",
157 i, m->msg_style);
158 goto err;
162 * fix up final newline:
163 * removed for prompts
164 * added back for messages
166 if (m->msg[strlen(m->msg)] == '\n')
167 m->msg[strlen(m->msg)] = '\0';
169 r->resp = NULL;
170 r->resp_retcode = 0;
171 echo_off = 0;
172 switch (m->msg_style) {
174 case PAM_PROMPT_ECHO_OFF:
175 echo_off = 1;
176 /*FALLTHROUGH*/
178 case PAM_PROMPT_ECHO_ON:
179 (void) fputs(m->msg, stdout);
181 r->resp = getinput(echo_off);
182 break;
184 case PAM_ERROR_MSG:
185 (void) fputs(m->msg, stderr);
186 (void) fputc('\n', stderr);
187 break;
189 case PAM_TEXT_INFO:
190 (void) fputs(m->msg, stdout);
191 (void) fputc('\n', stdout);
192 break;
194 default:
195 (void) fprintf(stderr, "message[%d]: unknown type "
196 "%d/val=\"%s\"\n",
197 i, m->msg_style, m->msg);
198 /* error, service module won't clean up */
199 goto err;
201 if (errno == EINTR)
202 goto err;
204 /* next message/response */
205 m++;
206 r++;
208 return (PAM_SUCCESS);
210 err:
211 free_resp(i, r);
212 *resp = NULL;
213 return (PAM_CONV_ERR);