xref: /illumos-gate/usr/src/cmd/ttymon/sttyparse.c (revision 00277c9e43668ff248a12ee635ce125957750373)
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 1999-2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
26  */
27 
28 /*
29  * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
30  * All Rights Reserved
31  *
32  */
33 
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <libintl.h>
38 #include <sys/types.h>
39 #include <ctype.h>
40 #include <termio.h>
41 #include <sys/stermio.h>
42 #include <sys/termiox.h>
43 #ifdef EUC
44 #include <sys/param.h>
45 #include <sys/stropts.h>
46 #include <sys/eucioctl.h>
47 #include <sys/csiioctl.h>
48 #include <sys/stream.h>
49 #include <sys/termios.h>
50 #include <sys/ldterm.h>
51 #include <getwidth.h>
52 #endif /* EUC */
53 #include "stty.h"
54 #include <locale.h>
55 #include <string.h>
56 
57 static char	*s_arg;			/* s_arg: ptr to mode to be set */
58 static int	match;
59 #ifdef EUC
60 static int parse_encoded(struct termios *, ldterm_cs_data_user_t *, int);
61 #else
62 static int parse_encoded(struct termios *);
63 #endif /* EUC */
64 static int eq(const char *string);
65 static int gct(char *cp, int term);
66 
67 /* set terminal modes for supplied options */
68 char *
69 sttyparse(int argc, char *argv[], int term, struct termio *ocb,
70 	struct termios *cb, struct termiox *termiox, struct winsize *winsize
71 #ifdef EUC
72 	/* */, eucwidth_t *wp, struct eucioc *kwp, ldterm_cs_data_user_t *cswp,
73 	ldterm_cs_data_user_t *kcswp
74 #endif /* EUC */
75 	/* */)
76 {
77 	int i;
78 
79 	while (--argc > 0) {
80 		s_arg = *++argv;
81 		match = 0;
82 		if (term & ASYNC) {
83 			if (eq("erase") && --argc)
84 				cb->c_cc[VERASE] = gct(*++argv, term);
85 			else if (eq("intr") && --argc)
86 				cb->c_cc[VINTR] = gct(*++argv, term);
87 			else if (eq("quit") && --argc)
88 				cb->c_cc[VQUIT] = gct(*++argv, term);
89 			else if (eq("eof") && --argc)
90 				cb->c_cc[VEOF] = gct(*++argv, term);
91 			else if (eq("min") && --argc) {
92 				if (isdigit((unsigned char)argv[1][0]))
93 					cb->c_cc[VMIN] = atoi(*++argv);
94 				else
95 					cb->c_cc[VMIN] = gct(*++argv, term);
96 			} else if (eq("eol") && --argc)
97 				cb->c_cc[VEOL] = gct(*++argv, term);
98 			else if (eq("eol2") && --argc)
99 				cb->c_cc[VEOL2] = gct(*++argv, term);
100 			else if (eq("time") && --argc) {
101 				if (isdigit((unsigned char)argv[1][0]))
102 					cb->c_cc[VTIME] = atoi(*++argv);
103 				else
104 					cb->c_cc[VTIME] = gct(*++argv, term);
105 			} else if (eq("kill") && --argc)
106 				cb->c_cc[VKILL] = gct(*++argv, term);
107 			else if (eq("swtch") && --argc)
108 				cb->c_cc[VSWTCH] = gct(*++argv, term);
109 			if (match)
110 				continue;
111 			if (term & TERMIOS) {
112 				if (eq("start") && --argc)
113 					cb->c_cc[VSTART] = gct(*++argv, term);
114 				else if (eq("stop") && --argc)
115 					cb->c_cc[VSTOP] = gct(*++argv, term);
116 				else if (eq("susp") && --argc)
117 					cb->c_cc[VSUSP] = gct(*++argv, term);
118 				else if (eq("dsusp") && --argc)
119 					cb->c_cc[VDSUSP] = gct(*++argv, term);
120 				else if (eq("rprnt") && --argc)
121 					cb->c_cc[VREPRINT] = gct(*++argv, term);
122 				else if (eq("reprint") && --argc)
123 					cb->c_cc[VREPRINT] = gct(*++argv, term);
124 				else if (eq("discard") && --argc)
125 					cb->c_cc[VDISCARD] = gct(*++argv, term);
126 				else if (eq("flush") && --argc)
127 					cb->c_cc[VDISCARD] = gct(*++argv, term);
128 				else if (eq("werase") && --argc)
129 					cb->c_cc[VWERASE] = gct(*++argv, term);
130 				else if (eq("lnext") && --argc)
131 					cb->c_cc[VLNEXT] = gct(*++argv, term);
132 				else if (eq("status") && --argc)
133 					cb->c_cc[VSTATUS] = gct(*++argv, term);
134 			}
135 			if (match)
136 				continue;
137 			if (eq("ek")) {
138 				cb->c_cc[VERASE] = CERASE;
139 				cb->c_cc[VKILL] = CKILL;
140 			} else if (eq("line") &&
141 			    !(term & TERMIOS) && --argc) {
142 				ocb->c_line = atoi(*++argv);
143 				continue;
144 			} else if (eq("raw")) {
145 				cb->c_cc[VMIN] = 1;
146 				cb->c_cc[VTIME] = 0;
147 			} else if (eq("-raw") | eq("cooked")) {
148 				cb->c_cc[VEOF] = CEOF;
149 				cb->c_cc[VEOL] = CNUL;
150 			} else if (eq("sane")) {
151 				cb->c_cc[VERASE] = CERASE;
152 				cb->c_cc[VKILL] = CKILL;
153 				cb->c_cc[VQUIT] = CQUIT;
154 				cb->c_cc[VINTR] = CINTR;
155 				cb->c_cc[VEOF] = CEOF;
156 				cb->c_cc[VEOL] = CNUL;
157 				cb->c_cc[VSTATUS] = CSTATUS;
158 				/* SWTCH purposely not set */
159 #ifdef EUC
160 			} else if (eq("defeucw")) {
161 				kwp->eucw[0] = '\001';
162 				kwp->eucw[1] =
163 				    (unsigned char)(wp->_eucw1 & 0177);
164 				kwp->eucw[2] =
165 				    (unsigned char)(wp->_eucw2 & 0177);
166 				kwp->eucw[3] =
167 				    (unsigned char)(wp->_eucw3 & 0177);
168 
169 				kwp->scrw[0] = '\001';
170 				kwp->scrw[1] =
171 				    (unsigned char)(wp->_scrw1 & 0177);
172 				kwp->scrw[2] =
173 				    (unsigned char)(wp->_scrw2 & 0177);
174 				kwp->scrw[3] =
175 				    (unsigned char)(wp->_scrw3 & 0177);
176 
177 				(void) memcpy((void *)kcswp, (const void *)cswp,
178 				    sizeof (ldterm_cs_data_user_t));
179 #endif /* EUC */
180 			} else if ((term & TERMIOS) && eq("ospeed") && --argc) {
181 				s_arg = *++argv;
182 				for (match = 0, i = 0; speeds[i].string; i++) {
183 					if (eq(speeds[i].string)) {
184 						(void) cfsetospeed(cb,
185 						    speeds[i].code);
186 						break;
187 					}
188 				}
189 				if (!match)
190 					return (s_arg);
191 				continue;
192 
193 			} else if ((term & TERMIOS) && eq("ispeed") && --argc) {
194 				s_arg = *++argv;
195 				for (match = 0, i = 0; speeds[i].string; i++) {
196 					if (eq(speeds[i].string)) {
197 						(void) cfsetispeed(cb,
198 						    speeds[i].code);
199 						break;
200 					}
201 				}
202 				if (!match)
203 					return (s_arg);
204 				continue;
205 
206 			} else {
207 				for (match = 0, i = 0; speeds[i].string; i++) {
208 					if (eq(speeds[i].string)) {
209 						(void) cfsetospeed(cb,
210 						    speeds[i].code);
211 						(void) cfsetispeed(cb,
212 						    speeds[i].code);
213 						break;
214 					}
215 				}
216 			}
217 		}
218 		if (!(term & ASYNC) && eq("ctab") && --argc) {
219 			cb->c_cc[7] = gct(*++argv, term);
220 			continue;
221 		}
222 
223 		for (i = 0; imodes[i].string; i++)
224 			if (eq(imodes[i].string)) {
225 				cb->c_iflag &= ~imodes[i].reset;
226 				cb->c_iflag |= imodes[i].set;
227 #ifdef EUC
228 				if (wp->_multibyte &&
229 				    (eq("-raw") || eq("cooked") || eq("sane")))
230 					cb->c_iflag &= ~ISTRIP;
231 #endif /* EUC */
232 			}
233 		if (term & TERMIOS) {
234 			for (i = 0; nimodes[i].string; i++)
235 				if (eq(nimodes[i].string)) {
236 					cb->c_iflag &= ~nimodes[i].reset;
237 					cb->c_iflag |= nimodes[i].set;
238 				}
239 		}
240 
241 		for (i = 0; omodes[i].string; i++)
242 			if (eq(omodes[i].string)) {
243 				cb->c_oflag &= ~omodes[i].reset;
244 				cb->c_oflag |= omodes[i].set;
245 			}
246 		if (!(term & ASYNC) && eq("sane")) {
247 			cb->c_oflag |= TAB3;
248 			continue;
249 		}
250 		for (i = 0; cmodes[i].string; i++)
251 			if (eq(cmodes[i].string)) {
252 				cb->c_cflag &= ~cmodes[i].reset;
253 				cb->c_cflag |= cmodes[i].set;
254 #ifdef EUC
255 				if (wp->_multibyte &&
256 				    (eq("-raw") || eq("cooked") ||
257 				    eq("sane"))) {
258 					cb->c_cflag &= ~(CS7|PARENB);
259 					cb->c_cflag |= CS8;
260 				}
261 #endif /* EUC */
262 			}
263 		if (term & TERMIOS)
264 			for (i = 0; ncmodes[i].string; i++)
265 				if (eq(ncmodes[i].string)) {
266 					cb->c_cflag &= ~ncmodes[i].reset;
267 					cb->c_cflag |= ncmodes[i].set;
268 				}
269 		for (i = 0; lmodes[i].string; i++)
270 			if (eq(lmodes[i].string)) {
271 				cb->c_lflag &= ~lmodes[i].reset;
272 				cb->c_lflag |= lmodes[i].set;
273 			}
274 		if (term & TERMIOS)
275 			for (i = 0; nlmodes[i].string; i++)
276 				if (eq(nlmodes[i].string)) {
277 					cb->c_lflag &= ~nlmodes[i].reset;
278 					cb->c_lflag |= nlmodes[i].set;
279 				}
280 		if (term & FLOW) {
281 			for (i = 0; hmodes[i].string; i++)
282 				if (eq(hmodes[i].string)) {
283 					termiox->x_hflag &= ~hmodes[i].reset;
284 					termiox->x_hflag |= hmodes[i].set;
285 				}
286 			for (i = 0; clkmodes[i].string; i++)
287 				if (eq(clkmodes[i].string)) {
288 					termiox->x_cflag &= ~clkmodes[i].reset;
289 					termiox->x_cflag |= clkmodes[i].set;
290 				}
291 
292 		}
293 
294 		if (eq("rows") && --argc)
295 			winsize->ws_row = atoi(*++argv);
296 		else if ((eq("columns") || eq("cols")) && --argc)
297 			winsize->ws_col = atoi(*++argv);
298 		else if (eq("xpixels") && --argc)
299 			winsize->ws_xpixel = atoi(*++argv);
300 		else if (eq("ypixels") && --argc)
301 			winsize->ws_ypixel = atoi(*++argv);
302 
303 		if (!match) {
304 #ifdef EUC
305 			if (!parse_encoded(cb, kcswp, term)) {
306 #else
307 			if (!parse_encoded(cb)) {
308 #endif /* EUC */
309 				return (s_arg); /* parsing failed */
310 			}
311 		}
312 	}
313 	return ((char *)0);
314 }
315 
316 static int
317 eq(const char *string)
318 {
319 	int i;
320 
321 	if (!s_arg)
322 		return (0);
323 	i = 0;
324 loop:
325 	if (s_arg[i] != string[i])
326 		return (0);
327 	if (s_arg[i++] != '\0')
328 		goto loop;
329 	match++;
330 	return (1);
331 }
332 
333 /* get pseudo control characters from terminal  */
334 /* and convert to internal representation	*/
335 static int
336 gct(char *cp, int term)
337 {
338 	int c;
339 
340 	c = *cp;
341 	if (c == '^') {
342 		c = *++cp;
343 		if (c == '?')
344 			c = 0177;		/* map '^?' to 0177 */
345 		else if (c == '-') {
346 			/* map '^-' to undefined */
347 			c = (term & TERMIOS) ? _POSIX_VDISABLE : 0200;
348 		} else
349 			c &= 037;
350 	} else if (strcmp(cp, "undef") == 0) {
351 		/* map "undef" to undefined */
352 		c = (term & TERMIOS) ? _POSIX_VDISABLE : 0200;
353 	}
354 	return (c);
355 }
356 
357 /* get modes of tty device and fill in applicable structures */
358 int
359 get_ttymode(int fd, struct termio *termio, struct termios *termios,
360 	struct stio *stermio, struct termiox *termiox, struct winsize *winsize
361 #ifdef EUC
362 	/* */, struct eucioc *kwp, ldterm_cs_data_user_t *kcswp
363 #endif /* EUC */
364 	/* */)
365 {
366 	int i;
367 	int term = 0;
368 #ifdef EUC
369 	struct strioctl cmd;
370 #endif /* EUC */
371 	if (ioctl(fd, STGET, stermio) == -1) {
372 		term |= ASYNC;
373 		if (ioctl(fd, TCGETS, termios) == -1) {
374 			if (ioctl(fd, TCGETA, termio) == -1)
375 				return (-1);
376 			termios->c_lflag = termio->c_lflag;
377 			termios->c_oflag = termio->c_oflag;
378 			termios->c_iflag = termio->c_iflag;
379 			termios->c_cflag = termio->c_cflag;
380 			for (i = 0; i < NCC; i++)
381 				termios->c_cc[i] = termio->c_cc[i];
382 		} else
383 			term |= TERMIOS;
384 	} else {
385 		termios->c_cc[7] = (unsigned)stermio->tab;
386 		termios->c_lflag = stermio->lmode;
387 		termios->c_oflag = stermio->omode;
388 		termios->c_iflag = stermio->imode;
389 	}
390 
391 	if (ioctl(fd, TCGETX, termiox) == 0)
392 		term |= FLOW;
393 
394 	if (ioctl(fd, TIOCGWINSZ, winsize) == 0)
395 		term |= WINDOW;
396 #ifdef EUC
397 	cmd.ic_cmd = EUC_WGET;
398 	cmd.ic_timout = 0;
399 	cmd.ic_len = sizeof (struct eucioc);
400 	cmd.ic_dp = (char *)kwp;
401 
402 	if (ioctl(fd, I_STR, &cmd) == 0)
403 		term |= EUCW;
404 
405 	cmd.ic_cmd = CSDATA_GET;
406 	cmd.ic_timout = 0;
407 	cmd.ic_len = sizeof (ldterm_cs_data_user_t);
408 	cmd.ic_dp = (char *)kcswp;
409 
410 	if (ioctl(fd, I_STR, &cmd) == 0)
411 		term |= CSIW;
412 	else
413 		(void) memset((void *)kcswp, 0, sizeof (ldterm_cs_data_user_t));
414 #endif /* EUC */
415 	return (term);
416 }
417 
418 /* set tty modes */
419 int
420 set_ttymode(int fd, int term, struct termio *termio, struct termios *termios,
421 	struct stio *stermio, struct termiox *termiox, struct winsize *winsize,
422 	struct winsize *owinsize
423 #ifdef EUC
424 	/* */, struct eucioc *kwp, ldterm_cs_data_user_t *kcswp,
425 	int invalid_ldterm_dat_file
426 #endif /* EUC */
427 	/* */)
428 {
429 	int i;
430 #ifdef EUC
431 	struct strioctl cmd;
432 #endif /* EUC */
433 
434 	if (term & ASYNC) {
435 		if (term & TERMIOS) {
436 			if (ioctl(fd, TCSETSW, termios) == -1)
437 				return (-1);
438 		} else {
439 			termio->c_lflag = termios->c_lflag;
440 			termio->c_oflag = termios->c_oflag;
441 			termio->c_iflag = termios->c_iflag;
442 			termio->c_cflag = termios->c_cflag;
443 			for (i = 0; i < NCC; i++)
444 				termio->c_cc[i] = termios->c_cc[i];
445 			if (ioctl(fd, TCSETAW, termio) == -1)
446 				return (-1);
447 		}
448 
449 	} else {
450 		stermio->imode = termios->c_iflag;
451 		stermio->omode = termios->c_oflag;
452 		stermio->lmode = termios->c_lflag;
453 		stermio->tab = termios->c_cc[7];
454 		if (ioctl(fd, STSET, stermio) == -1)
455 			return (-1);
456 	}
457 	if (term & FLOW) {
458 		if (ioctl(fd, TCSETXW, termiox) == -1)
459 			return (-1);
460 	}
461 	if ((owinsize->ws_col != winsize->ws_col ||
462 	    owinsize->ws_row != winsize->ws_row ||
463 	    owinsize->ws_xpixel != winsize->ws_xpixel ||
464 	    owinsize->ws_ypixel != winsize->ws_ypixel) &&
465 	    ioctl(0, TIOCSWINSZ, winsize) != 0)
466 		return (-1);
467 #ifdef EUC
468 	/*
469 	 * If the ldterm.dat file contains valid, non-EUC codeset info,
470 	 * send downstream CSDATA_SET. Otherwise, try EUC_WSET.
471 	 */
472 	if (invalid_ldterm_dat_file) {
473 		(void) fprintf(stderr, gettext(
474 		"stty: can't set codeset width due to invalid ldterm.dat.\n"));
475 		return (-1);
476 	} else if ((term & CSIW) && kcswp->version) {
477 		cmd.ic_cmd = CSDATA_SET;
478 		cmd.ic_timout = 0;
479 		cmd.ic_len = sizeof (ldterm_cs_data_user_t);
480 		cmd.ic_dp = (char *)kcswp;
481 		if (ioctl(fd, I_STR, &cmd) != 0) {
482 			(void) fprintf(stderr, gettext(
483 			    "stty: can't set codeset width.\n"));
484 			return (-1);
485 		}
486 	} else if (term & EUCW) {
487 		cmd.ic_cmd = EUC_WSET;
488 		cmd.ic_timout = 0;
489 		cmd.ic_len = sizeof (struct eucioc);
490 		cmd.ic_dp = (char *)kwp;
491 		if (ioctl(fd, I_STR, &cmd) != 0) {
492 			(void) fprintf(stderr, gettext(
493 			    "stty: can't set EUC codeset width.\n"));
494 			return (-1);
495 		}
496 	}
497 #endif /* EUC */
498 	return (0);
499 }
500 
501 static int
502 parse_encoded(struct termios *cb
503 #ifdef EUC
504 	/* */, ldterm_cs_data_user_t *kcswp, int term
505 #endif /* EUC */
506 	/* */)
507 {
508 	unsigned long grab[NUM_FIELDS];
509 	int last, i;
510 #ifdef EUC
511 	long l;
512 	char s[3];
513 	char *t;
514 	char *r;
515 	uchar_t *g;
516 	ldterm_cs_data_user_t ecswp;
517 #endif /* EUC */
518 
519 	/*
520 	 * Although there are only 16 control chars defined as of April 1995,
521 	 * parse_encoded() and prencode()  will not have to be changed if up to
522 	 * MAX_CC control chars are defined in the future.
523 	 * Scan the fields of "stty -g" output into the grab array.
524 	 * Set a total of NUM_FIELDS fields (NUM_MODES modes + MAX_CC
525 	 * control chars).
526 	 */
527 	i = sscanf(s_arg, "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:"
528 	    "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
529 	    &grab[0], &grab[1], &grab[2], &grab[3], &grab[4], &grab[5],
530 	    &grab[6], &grab[7], &grab[8], &grab[9], &grab[10], &grab[11],
531 	    &grab[12], &grab[13], &grab[14], &grab[15],	&grab[16], &grab[17],
532 	    &grab[18], &grab[19], &grab[20], &grab[21]);
533 
534 	if (i < 12)
535 		return (0);
536 	cb->c_iflag = grab[0];
537 	cb->c_oflag = grab[1];
538 	cb->c_cflag = grab[2];
539 	cb->c_lflag = grab[3];
540 
541 	last = i - NUM_MODES;
542 	for (i = 0; i < last; i++)
543 		cb->c_cc[i] = (unsigned char) grab[i+NUM_MODES];
544 
545 #ifdef EUC
546 	/* This is to fulfill PSARC/1999/140 TCR2. */
547 	if (term & CSIW) {
548 		r = strdup(s_arg);
549 		if (r == (char *)NULL) {
550 			(void) fprintf(stderr, gettext(
551 			    "no more memory - try again later\n"));
552 			return (0);
553 		}
554 		t = strtok(r, ":");
555 		for (i = 0; t != NULL && i < 22; i++) {
556 			t = strtok(NULL, ":");
557 		}
558 
559 		if (t == NULL) {
560 			free((void *)r);
561 			return (0);
562 		}
563 		ecswp.version = (uchar_t)strtol(t, (char **)NULL, 16);
564 		if (ecswp.version > LDTERM_DATA_VERSION ||
565 		    ecswp.version == 0) {
566 			free((void *)r);
567 			return (0);
568 		}
569 
570 		if ((t = strtok(NULL, ":")) == NULL) {
571 			free((void *)r);
572 			return (0);
573 		}
574 		ecswp.codeset_type = (uchar_t)strtol(t, (char **)NULL, 16);
575 		if (ecswp.codeset_type < LDTERM_CS_TYPE_MIN ||
576 		    ecswp.codeset_type > LDTERM_CS_TYPE_MAX) {
577 			free((void *)r);
578 			return (0);
579 		}
580 
581 		if ((t = strtok(NULL, ":")) == NULL) {
582 			free((void *)r);
583 			return (0);
584 		}
585 		ecswp.csinfo_num = (uchar_t)strtol(t, (char **)NULL, 16);
586 		if ((ecswp.codeset_type == LDTERM_CS_TYPE_EUC &&
587 		    ecswp.csinfo_num > 3) ||
588 		    (ecswp.codeset_type == LDTERM_CS_TYPE_PCCS &&
589 		    (ecswp.csinfo_num < 1 || ecswp.csinfo_num > 10))) {
590 			free((void *)r);
591 			return (0);
592 		}
593 
594 		if ((t = strtok(NULL, ":")) == NULL) {
595 			free((void *)r);
596 			return (0);
597 		}
598 		s[2] = '\0';
599 		for (i = 0; *t != 0 && i < MAXNAMELEN; i++) {
600 			if (*(t + 1) == (char)NULL) {
601 				free((void *)r);
602 				return (0);
603 			}
604 			s[0] = *t++;
605 			s[1] = *t++;
606 			ecswp.locale_name[i] = (char)strtol(s, (char **)NULL,
607 			    16);
608 		}
609 		if (i >= MAXNAMELEN) {
610 			free((void *)r);
611 			return (0);
612 		}
613 		ecswp.locale_name[i] = '\0';
614 
615 		g = (uchar_t *)ecswp.eucpc_data;
616 		for (i = 0; i < (LDTERM_CS_MAX_CODESETS * 4); i++) {
617 			if ((t = strtok(NULL, ":")) == NULL) {
618 				free((void *)r);
619 				return (0);
620 			}
621 			l = strtol(t, (char **)NULL, 16);
622 			if (l < 0 || l > 255) {
623 				free((void *)r);
624 				return (0);
625 			}
626 			*g++ = (uchar_t)l;
627 		}
628 
629 		/* We got the 'ecswp' all filled up now; let's copy. */
630 		(void) memcpy((void *)kcswp, (const void *)&ecswp,
631 		    sizeof (ldterm_cs_data_user_t));
632 	}
633 #endif /* EUC */
634 
635 	return (1);
636 }
637