1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * modem_setup.c: support for the scadm modem_setup option (access to the
29  * service processor modem - if present)
30  */
31 
32 #include <curses.h>
33 #include <libintl.h>
34 #include <pthread.h>
35 #include <signal.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <time.h>  /* required by librsc.h */
39 #include <unistd.h>
40 
41 #include "librsc.h"
42 #include "adm.h"
43 
44 
45 extern char *ADM_Get_Var(char *Variable);
46 
47 static void ADM_Send_Char(char  C);
48 static void *ADM_Modem_Listen(void *);
49 static void cleanup();
50 
51 
52 typedef enum {ST_RESET, ST_IDLE, ST_TILDA} ADM_state_t;
53 
54 static int ADM_Continue;
55 static int winOn = 0;
56 static pthread_t modemListen;
57 
58 
59 void
ADM_Process_modem_setup(void)60 ADM_Process_modem_setup(void)
61 {
62 	rscp_msg_t	msg;
63 	struct timespec	timeout;
64 
65 	int		Input;
66 	ADM_state_t	State;
67 	int		exitLoop = 1;
68 	char		rsc_escape[2];
69 	char		string[40];
70 
71 
72 	ADM_Start();
73 
74 	msg.type = DP_MODEM_CONNECT;
75 	msg.len  = 0;
76 	msg.data = NULL;
77 	ADM_Send(&msg);
78 
79 	timeout.tv_nsec = 0;
80 	timeout.tv_sec  = ADM_TIMEOUT;
81 	ADM_Recv(&msg, &timeout, DP_MODEM_CONNECT_R,
82 	    sizeof (dp_modem_connect_r_t));
83 	if (*(int *)msg.data != DP_MODEM_PASS) {
84 		(void) fprintf(stderr, "\n%s\n\n",
85 		    gettext("scadm: could not connect to modem"));
86 		exit(-1);
87 	}
88 	ADM_Free(&msg);
89 
90 	/* Get the escape char BEFORE starting up the "listen" thread */
91 	(void) strcpy(rsc_escape, ADM_Get_Var("escape_char"));
92 
93 
94 	/* Create Listening Thread */
95 	ADM_Continue = 1;
96 	if (pthread_create(&modemListen, NULL, ADM_Modem_Listen, NULL) != 0) {
97 		(void) fprintf(stderr, "\n%s\n\n",
98 		    gettext("scadm: couldn't create thread"));
99 		exit(-1);
100 	}
101 
102 	if (signal(SIGINT, cleanup) == SIG_ERR) {
103 		(void) fprintf(stderr, "\n%s\n\n",
104 		    gettext("scadm: cleanup() registration failed"));
105 		ADM_Continue = 0;
106 		exit(-1);
107 	}
108 
109 
110 	(void) sprintf(string, gettext("... Type %s. to return to prompt ..."),
111 	    rsc_escape);
112 	Input = 0;
113 	State = ST_RESET;
114 	winOn = 1;
115 	initscr();
116 	noecho();
117 	printw("\n%s\n\n", string);
118 
119 	while (exitLoop) {
120 		while ((Input = getch()) == ERR)
121 			;
122 
123 		if (Input == 10) {
124 			State = ST_RESET;
125 			ADM_Send_Char('\n');
126 			ADM_Send_Char('\r');
127 			continue;
128 		}
129 
130 		switch (State) {
131 			case ST_RESET:
132 				if ((char)Input == rsc_escape[0]) {
133 					State = ST_TILDA;
134 				} else {
135 					State = ST_IDLE;
136 					ADM_Send_Char((char)Input);
137 				}
138 				break;
139 
140 			case ST_IDLE:
141 				ADM_Send_Char((char)Input);
142 				break;
143 
144 			case ST_TILDA:
145 				if ((char)Input == '.') {
146 					ADM_Send_Char('~');
147 					ADM_Send_Char('.');
148 					exitLoop = 0;
149 				} else {
150 					State = ST_IDLE;
151 					ADM_Send_Char((char)Input);
152 				}
153 				break;
154 
155 			default:
156 				State = ST_IDLE;
157 				ADM_Send_Char((char)Input);
158 		}
159 	}
160 	endwin();
161 	winOn = 0;
162 
163 	/* Terminate Thread */
164 	ADM_Continue = 0;
165 	(void) sleep(3);	/* Make sure thread has time to 'see' */
166 				/* termination */
167 
168 	msg.type = DP_MODEM_DISCONNECT;
169 	msg.len  = 0;
170 	msg.data = NULL;
171 	ADM_Send(&msg);
172 
173 	timeout.tv_nsec = 0;
174 	timeout.tv_sec  = ADM_TIMEOUT;
175 	ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
176 	    sizeof (dp_modem_disconnect_r_t));
177 	if (*(int *)msg.data != DP_MODEM_PASS) {
178 		(void) fprintf(stderr, "\n%s\n\n",
179 		    gettext("scadm: could not disconnect from modem"));
180 		ADM_Continue = 0;
181 		exit(-1);
182 	}
183 	ADM_Free(&msg);
184 
185 	pthread_join(modemListen, NULL);
186 
187 }
188 
189 
190 static void
ADM_Send_Char(char C)191 ADM_Send_Char(char C)
192 {
193 	rscp_msg_t	Message;
194 	char		Data[2];
195 
196 	Data[0] = C;
197 	Data[1] = 0x0;
198 	Message.type = DP_MODEM_DATA;
199 	Message.len  = 2;
200 	Message.data = Data;
201 
202 	if (rscp_send(&Message) != 0) {
203 		(void) fprintf(stderr, "\n%s\n\n",
204 		    gettext("scadm: Unable to send modem data to SC"));
205 		if (winOn)
206 			endwin();
207 		ADM_Continue = 0;
208 		exit(-1);
209 	}
210 }
211 
212 
213 static void *
ADM_Modem_Listen(void * arg __unused)214 ADM_Modem_Listen(void *arg __unused)
215 {
216 	rscp_msg_t	Message;
217 	struct timespec	Timeout;
218 
219 
220 	while (ADM_Continue) {
221 		Timeout.tv_nsec = 500000000;
222 		Timeout.tv_sec  = 0;
223 		if (rscp_recv(&Message, &Timeout) != 0) {
224 			continue;
225 		}
226 
227 		if (Message.type != DP_MODEM_DATA) {
228 			(void) fprintf(stderr, "\n%s: 0x%08x:0x%08lx\n\n",
229 			    gettext("scadm: SC returned garbage"),
230 			    Message.type, Message.len);
231 			exit(-1);
232 		}
233 
234 		(void) printf("%s", (char *)Message.data);
235 		(void) fflush(stdout);
236 		ADM_Free(&Message);
237 	}
238 	return (NULL);
239 }
240 
241 
242 static void
cleanup()243 cleanup()
244 {
245 	rscp_msg_t	msg;
246 	struct timespec	timeout;
247 
248 
249 	if (winOn)
250 		endwin();
251 
252 	/* Terminate Thread */
253 	ADM_Continue = 0;
254 
255 	msg.type = DP_MODEM_DISCONNECT;
256 	msg.len  = 0;
257 	msg.data = NULL;
258 	ADM_Send(&msg);
259 
260 	timeout.tv_nsec = 0;
261 	timeout.tv_sec  = ADM_TIMEOUT;
262 	ADM_Recv(&msg, &timeout, DP_MODEM_DISCONNECT_R,
263 	    sizeof (dp_modem_disconnect_r_t));
264 	if (*(int *)msg.data != DP_MODEM_PASS) {
265 		(void) fprintf(stderr, "\n%s\n\n",
266 		    gettext("scadm: could not disconnect from modem"));
267 		exit(-1);
268 	}
269 	ADM_Free(&msg);
270 
271 	pthread_join(modemListen, NULL);
272 
273 	exit(-1);
274 }
275