2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * File: spc-termio.c $TOG: spc-termio.c /main/5 1998/04/03 17:08:32 mgreess $
27 * (c) Copyright 1990, Hewlett-Packard Company, all rights reserved.
29 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
30 * (c) Copyright 1993, 1994 International Business Machines Corp. *
31 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
32 * (c) Copyright 1993, 1994 Novell, Inc. *
35 #include <bms/sbport.h>
36 #include <bms/stringbuf.h>
39 #if !defined(__linux__) && !defined(CSRG_BASED)
40 #include <sys/termio.h>
42 #include <codelibs/stringx.h>
47 #define STRTOKX(b,f) strtokx((b), (f))
49 #define STRTOKX(b,f) strtokx((char **)(&b), (f))
52 /***************************************************************************************
54 The routines in this file decode and encode a termios struct back and forth between the
55 actual binary representation of the structure and an ASCII string representation which
56 may be portably sent across the network.
58 <version>!<i-flags>!<o-flags>!<c-flags>!<l-flags>!<i-speed>!<o-speed>!<cc-array>
62 <version> == the termios struct protocal version (currently XPG3)
64 <i-flags> == comma separated list of input mode flags as defined in
65 the termios.h header file.
67 <o-flags> == comma separated list of output mode flags as defined in
68 the termios.h header file.
70 <c-flags> == comma separated list of control mode flags as defined in
71 the termios.h header file. The terminal speed info is
72 not part of this list.
74 <i-speed> == The input speed as defined in the termios.h header file.
76 <o-speed> == The output speed as defined in the termios.h header file.
78 <cc-array> == comma separated list of control control character names and
79 values formatted as (<name>=<value),<name>=<value>...)
81 ******************************************************************************************/
83 #define SPC_TERMIO_VER_FIELD 1 /* Define field indicies for above string */
84 #define SPC_TERMIO_IMODE_FIELD 2
85 #define SPC_TERMIO_OMODE_FIELD 3
86 #define SPC_TERMIO_CMODE_FIELD 4
87 #define SPC_TERMIO_LMODE_FIELD 5
88 #define SPC_TERMIO_ISPEED_FIELD 6
89 #define SPC_TERMIO_OSPEED_FIELD 7
90 #define SPC_TERMIO_CC_FIELD 8
91 #define SPC_TERMIO_LAST_FIELD SPC_TERMIO_CC_FIELD
93 #define SPC_TERMIO_SEP "!" /* These three MUST be only 1 char */
94 #define SPC_TCFLAG_SEP ","
95 #define SPC_CC_SEP "="
97 #define SPC_CC_FORMAT "%u" /* CC values are printed with this format */
117 /* The following lists are the valid componants of a "struct termios" */
118 /* as defined in XPG3. These MUST be kept up to date with the X/Open */
119 /* standard. No platform specific items can exist here as we pass this */
120 /* data to other systems on the network and they be from any vendor. */
121 /* -------------------------------------------------------------------- */
123 #define SPC_TERMIO_VERSION "XPG3"
125 #define END_OF_LIST "End_Of_List"
127 static struct modes_s Input_modes[] = {
128 { "BRKINT", BRKINT, },
130 { "IGNBRK", IGNBRK, },
132 { "IGNPAR", IGNPAR, },
135 { "ISTRIP", ISTRIP, },
138 { "PARMRK", PARMRK, },
142 static struct modes_s Output_modes[] = {
147 { "ONLRET", ONLRET, },
148 #if !defined(CSRG_BASED)
159 { "TABDLY", TABDLY, },
178 static struct baud_s Baud_rates[] = {
193 { "B19200", B19200, },
194 { "B38400", B38400, },
199 static struct modes_s Control_modes[] = {
205 { "CSTOPB", CSTOPB, },
207 { "PARENB", PARENB, },
208 { "PARODD", PARODD, },
210 { "CLOCAL", CLOCAL, },
215 static struct modes_s Local_modes[] = {
219 { "ECHONL", ECHONL, },
220 { "ICANON", ICANON, },
221 { "IEXTEN", IEXTEN, },
223 { "NOFLSH", NOFLSH, },
224 { "TOSTOP", TOSTOP, },
229 static struct cc_s CC_Array[] = {
232 { "VERASE", VERASE, },
237 { "VSTART", VSTART, },
245 /*----------------------------------------------------------------------+*/
247 SPC_Decode_TCflag(tcflag_t flag,
248 struct modes_s modes[],
250 /*----------------------------------------------------------------------+*/
252 Boolean first_time = TRUE;
254 /* Given a binary representation of flag (tcflag_t), convert */
255 /* it into a comma separated list of ASCII flag names. */
257 while (strcmp(modes->name, END_OF_LIST) != 0)
259 if ( (modes->value & flag) == modes->value)
264 XeAppendToStringBuffer(buff, SPC_TCFLAG_SEP);
266 XeAppendToStringBuffer(buff, modes->name);
271 /* We need at least one blank for strtokx to work when */
272 /* we take this string apart on the other side. */
273 /* --------------------------------------------------- */
275 XeAppendToStringBuffer(buff, (XeString)" ");
278 /*----------------------------------------------------------------------+*/
280 SPC_Encode_TCflag(XeString buff,
281 struct modes_s modes[])
282 /*----------------------------------------------------------------------+*/
284 /* Given a comma separated list of flag names, convert the list */
285 /* into a "tcflag_t" (binary) representation of that list. */
288 tcflag_t flag = (tcflag_t)0;
289 struct modes_s *orig_modes = modes;
294 while ((item = (XeString)STRTOKX(buff, SPC_TCFLAG_SEP)))
296 Boolean found = FALSE;
299 while (strcmp(modes->name, END_OF_LIST) != 0)
301 if (strcmp(modes->name, item) == 0)
303 flag |= modes->value;
311 SPC_Error(SPC_Bad_Termios_Mode, item);
317 /*----------------------------------------------------------------------+*/
319 SPC_Decode_Speed(speed_t speed,
320 struct baud_s bauds[],
322 /*----------------------------------------------------------------------+*/
324 /* Given a binary "speed_t" speed specification, convert it into */
325 /* a single ASCII string. */
327 while (strcmp(bauds->name, END_OF_LIST) != 0)
329 if (bauds->speed == speed)
331 XeAppendToStringBuffer(buff, bauds->name);
337 /* We need at least one blank for strtokx to work when */
338 /* we take this string apart on the other side. */
339 /* --------------------------------------------------- */
340 XeAppendToStringBuffer(buff, (XeString)" ");
343 /*----------------------------------------------------------------------+*/
345 SPC_Encode_Speed(XeString buff,
346 struct baud_s bauds[])
347 /*----------------------------------------------------------------------+*/
349 #define DEFAULT_SPEED B9600
351 /* Given a single ASCII name of a termio speed item, convert it into */
352 /* a binary (speed_t) representation. */
355 return DEFAULT_SPEED;
357 while (strcmp(bauds->name, END_OF_LIST) != 0)
359 if (strcmp(bauds->name, buff) == 0)
364 SPC_Error(SPC_Bad_Termios_Speed, buff);
365 return DEFAULT_SPEED;
368 /*----------------------------------------------------------------------+*/
370 SPC_Decode_CC(cc_t ccs[],
371 struct cc_s cc_array[],
373 /*----------------------------------------------------------------------+*/
375 Boolean first_time = TRUE;
377 /* Given an array of cc_s from a termios struct (binary */
378 /* representation), convert it into a comma sepearted list of */
379 /* CC names and values of the form <name>=<value> */
381 while (strcmp(cc_array->name, END_OF_LIST) != 0)
383 int index = ccs[cc_array->value];
391 XeAppendToStringBuffer(buff, SPC_TCFLAG_SEP);
393 XeAppendToStringBuffer(buff, cc_array->name);
394 XeAppendToStringBuffer(buff, SPC_CC_SEP);
395 sprintf(num, SPC_CC_FORMAT, index);
396 XeAppendToStringBuffer(buff, num);
401 /* We need at least one blank for strtokx to work when */
402 /* we take this string apart on the other side. */
403 /* --------------------------------------------------- */
405 XeAppendToStringBuffer(buff, (XeString)" ");
408 /*----------------------------------------------------------------------+*/
410 SPC_Encode_CC(XeString buff,
412 struct cc_s cc_array[])
413 /*----------------------------------------------------------------------+*/
415 /* we should have gotten a string that looks like this: */
417 /* <V-Name>=<value>,<V-Name>=<value>... */
419 /* For example: VEOF=4,VKILL=8 */
421 /* Parse this array and store the values in the "ccs" array passed in */
422 /* to us. It is assumed that the <V-name> strings are all defined in */
423 /* the "cc_array" list passed to us. */
424 /* ------------------------------------------------------------------ */
426 XeString cc_name, cc_value;
429 struct cc_s *orig_cc_array = cc_array;
431 for(i=0; i<NCCS; i++)
436 while ((cc_name = (XeString)STRTOKX(buff, SPC_TCFLAG_SEP)))
438 Boolean found = FALSE;
440 cc_value = strchr(cc_name, SPC_CC_SEP[0]); /* Go find the "=" */
443 SPC_Error(SPC_Bad_Termios_CC, cc_name);
446 *cc_value++ = XeChar_NULL; /* Replace "=" with null */
449 /* Look for "V-Name" in table ... */
450 /* ------------------------------ */
451 cc_array = orig_cc_array;
452 while (strcmp(cc_array->name, END_OF_LIST) != 0)
454 if (strcmp(cc_array->name, cc_name) == 0)
456 if (sscanf(cc_value, SPC_CC_FORMAT, &a_cc) != 1)
458 *(cc_value-1) = SPC_CC_SEP[0];
459 SPC_Error(SPC_Bad_Termios_CC, cc_name);
462 ccs[cc_array->value] = a_cc;
472 *(cc_value-1) = SPC_CC_SEP[0];
473 SPC_Error(SPC_Bad_Termios_CC, cc_name);
478 /*----------------------------------------------------------------------+*/
479 XeString SPC_Decode_Termios(struct termios *tio)
480 /*----------------------------------------------------------------------+*/
482 /* Given a termios struct, return an ascii string representation of */
483 /* it as defined at the front of this file. */
485 #define RESULT_BUFF_SIZE 32
489 XeStringBuffer result = XeMakeStringBuffer(RESULT_BUFF_SIZE);
491 XeAppendToStringBuffer(result, SPC_TERMIO_VERSION);
492 XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
494 SPC_Decode_TCflag(tio->c_iflag, Input_modes, result);
495 XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
497 SPC_Decode_TCflag(tio->c_oflag, Output_modes, result);
498 XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
500 SPC_Decode_TCflag(tio->c_cflag, Control_modes, result);
501 XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
503 SPC_Decode_TCflag(tio->c_lflag, Local_modes, result);
504 XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
506 speed = cfgetispeed(tio);
507 SPC_Decode_Speed(speed, Baud_rates, result);
508 XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
510 speed = cfgetospeed(tio);
511 SPC_Decode_Speed(speed, Baud_rates, result);
512 XeAppendToStringBuffer(result, SPC_TERMIO_SEP);
514 SPC_Decode_CC(tio->c_cc, CC_Array, result);
516 all = strdup(result->buffer);
518 XeFree(result->buffer);
524 /*----------------------------------------------------------------------+*/
525 void SPC_Encode_Termios(XeString buff, struct termios *tio)
526 /*----------------------------------------------------------------------+*/
528 /* Decodes the ascii representation of the termios struct. The format */
529 /* of the string is defined at the front of this file. */
532 XeString protocol_version;
536 while ((item = (XeString)STRTOKX(buff, SPC_TERMIO_SEP)))
538 /* We can possibly have an all blank field. Walk past them */
539 /* because the routines we will be calling don't expect any */
540 /* blanks in the string (but they do check for empty stings).*/
541 while (*item == (XeChar)' ') item++;
545 case SPC_TERMIO_VER_FIELD :
546 protocol_version = item;
547 /* Check this some day ??? */
550 case SPC_TERMIO_IMODE_FIELD :
551 tio->c_iflag = SPC_Encode_TCflag(item, Input_modes);
554 case SPC_TERMIO_OMODE_FIELD :
555 tio->c_oflag = SPC_Encode_TCflag(item, Output_modes);
558 case SPC_TERMIO_CMODE_FIELD :
559 tio->c_cflag = SPC_Encode_TCflag(item, Control_modes);
562 case SPC_TERMIO_LMODE_FIELD :
563 tio->c_lflag = SPC_Encode_TCflag(item, Local_modes);
566 case SPC_TERMIO_ISPEED_FIELD :
567 speed = SPC_Encode_Speed(item, Baud_rates);
568 cfsetispeed(tio, speed);
571 case SPC_TERMIO_OSPEED_FIELD :
572 speed = SPC_Encode_Speed(item, Baud_rates);
573 cfsetospeed(tio, speed);
576 case SPC_TERMIO_CC_FIELD :
577 SPC_Encode_CC(item, tio->c_cc, CC_Array);
587 if (item_cnt != SPC_TERMIO_LAST_FIELD)
588 SPC_Error(SPC_Bad_Termios_Proto,
589 (XeString) ((item_cnt < SPC_TERMIO_LAST_FIELD) ? "Too Few" : "Too Many"));
594 /*----------------------------------------------------------------------+*/
596 /*----------------------------------------------------------------------+*/
600 struct termios tio, tio2;
603 tio.c_iflag = BRKINT | IGNPAR | ICRNL | IXON;
604 tio.c_oflag = OPOST | ONLCR;
605 tio.c_cflag = CS7 | CREAD | CLOCAL;
606 tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
609 for(i=0; i<NCCS; i++)
611 tio.c_cc[VERASE] = 101;
612 tio.c_cc[VEOF] = 102;
613 tio.c_cc[VSTOP] = 103;
622 for(i=0; i<NCCS; i++)
625 cfsetispeed(&tio, B9600);
626 cfsetospeed(&tio, B1200);
628 s1 = strdup(s = SPC_Decode_Termios(&tio));
629 printf("Decoded string=\n<%s>\n\n", s);
632 SPC_Encode_Termios(s, &tio2);
633 s2 = strdup(s = SPC_Decode_Termios(&tio2));
634 printf("String after Encoding/decoding=\n<%s>\n\n", s2);
636 if (strcmp(s1, s2) == 0)
637 printf("...Identical ...\n");
639 printf("...Mismatch ...\n");