1/***************************************************************************
2 * LPRng - An Extended Print Spooler System
3 *
4 * Copyright 1988-2003, Patrick Powell, San Diego, CA
5 *     papowell@lprng.com
6 * See LICENSE for conditions of use.
7 *
8 ***************************************************************************/
9
10 static char *const _id =
11"$Id: stty.c,v 1.1.1.1 2008/10/15 03:28:27 james26_jang Exp $";
12
13
14#include "lp.h"
15#include "stty.h"
16/**** ENDINCLUDE ****/
17
18#if USE_STTY == TERMIO
19# ifdef HAVE_TERMIO_H
20#    include <termio.h>
21#  endif
22#  ifdef HAVE_SYS_TERMIO_H
23#    include <sys/termio.h>
24#  endif
25#endif
26
27#if USE_STTY == SGTTYB
28# include <sgtty.h>
29#endif
30
31#if USE_STTY == TERMIOS
32# include <termios.h>
33# ifdef USE_TERMIOX
34#  if defined(_SCO_DS) && !defined(_SVID3)
35#   define _SVID3 1   /* needed to enable #defines in SCO v5 termiox.h */
36#  endif
37#  include <sys/termiox.h>
38# endif
39#endif
40
41
42#if !defined(TIOCEXCL) && defined(HAVE_SYS_TTOLD_H) && !defined(IRIX)
43#  include <sys/ttold.h>
44#endif
45
46#if USE_STTY == SGTTYB
47
48# if !defined(B19200)
49#  ifdef EXTA
50#   define B19200 EXTA
51#  else
52#   define B19200 B9600
53#  endif  /* !defined(EXTA) */
54# endif  /* !defined(B19200) */
55
56#if !defined(B38400)
57#ifdef EXTB
58#define B38400 EXTB
59#else
60#define B38400 B9600
61#endif  /* !defined(EXTB) */
62#endif  /* !defined(B38400) */
63
64 static struct bauds {
65    char *string;
66    int baud;
67    int speed;
68} bauds[] = {
69
70    { "110", 110, B110, },
71    { "134", 134, B134, },
72    { "150", 150, B150, },
73    { "300", 300, B300, },
74    { "600", 600, B600, },
75    { "1200", 1200, B1200, },
76    { "1800", 1800, B1800, },
77    { "2400", 2400, B2400, },
78    { "4800", 4800, B4800, },
79    { "9600", 9600, B9600, },
80    { "19200", 19200, B19200, },
81    { "38400", 38400, B38400, },
82#if defined(B57600)
83    { "57600", 57600, B57600, },
84#endif
85#if defined(B115200)
86    { "115200", 115200, B115200, },
87#endif
88#if defined(B230400)
89    { "230400", 230400, B230400, },
90#endif
91#if defined(B460800)
92    { "460800", 460800, B460800, },
93#endif
94#if defined(B500000)
95    { "500000", 500000, B500000, },
96#endif
97#if defined(B576000)
98    { "576000", 576000, B576000, },
99#endif
100#if defined(B921600)
101    { "921600", 921600, B921600, },
102#endif
103    { (char *) 0, 0, 0 }
104};
105
106/*
107 * Set terminal modes.
108 *
109 * jmason: I've added support for some combination modes,
110 *  such as "pass8" and "parity".
111 */
112
113 struct tchars termctrl;
114 struct ltchars linectrl;
115 struct sgttyb mode;
116
117 static struct {
118    char *string;
119    int set;
120    int reset;
121    int lset;
122    int lreset;
123
124} modes[] = {
125    { "bs0", BS0, BS1, 0, 0 },
126    { "bs1", BS1, BS1, 0, 0 },
127    { "cbreak", CBREAK, 0, 0, 0 },
128    { "-cbreak", 0, CBREAK, 0, 0 },
129    { "cooked", 0, RAW, 0, 0 },
130    { "cr0", CR0, CR3, 0, 0 },
131    { "cr1", CR1, CR3, 0, 0 },
132    { "cr2", CR2, CR3, 0, 0 },
133    { "cr3", CR3, CR3, 0, 0 },
134    { "decctlq", 0, 0, LDECCTQ, 0 },
135    { "-decctlq", 0, 0, 0, LDECCTQ, },
136    { "echo", ECHO, 0, 0, 0 },
137    { "-echo", 0, ECHO, 0, 0 },
138    { "even", EVENP, 0, 0, 0 },
139    { "-even", 0, EVENP, 0, 0 },
140    { "ff0", FF0, FF1, 0, 0 },
141    { "ff1", FF1, FF1, 0, 0 },
142    { "lcase", LCASE, 0, 0, 0 },
143    { "-lcase", 0, LCASE, 0, 0 },
144    { "litout", 0, 0, LLITOUT, 0 },
145    { "-litout", 0, 0, 0, LLITOUT, },
146    { "nl", 0, CRMOD, 0, 0 },
147    { "-nl", CRMOD, 0, 0, 0 },
148    { "nl0", NL0, NL3, 0, 0 },
149    { "nl1", NL1, NL3, 0, 0 },
150    { "nl2", NL2, NL3, 0, 0 },
151    { "nl3", NL3, NL3, 0, 0 },
152    { "noflsh", 0, 0, LNOFLSH, 0 },
153    { "-noflsh", 0, 0, 0, LNOFLSH, },
154    { "nohang", 0, 0, LNOHANG, 0 },
155    { "-nohang", 0, 0, 0, LNOHANG, },
156    { "odd", ODDP, 0, 0, 0 },
157    { "-odd", 0, ODDP, 0, 0 },
158    { "raw", RAW, 0, 0, 0 },
159    { "-raw", 0, RAW, 0, 0 },
160    { "tab0", TAB0, XTABS, 0, 0 },
161    { "tab1", TAB1, XTABS, 0, 0 },
162    { "tab2", TAB2, XTABS, 0, 0 },
163    { "tabs", 0, XTABS, 0, 0 },
164    { "-tabs", XTABS, 0, 0, 0 },
165    { "tandem", TANDEM, 0, 0, 0 },
166    { "-tandem", 0, TANDEM, 0, 0 },
167#ifndef IS_NEXT
168    { "tilde", 0, 0, LTILDE, 0 },
169    { "-tilde", 0, 0, 0, LTILDE, },
170#endif
171    { "tn300", CR1, ALLDELAY, 0, 0 },
172    { "tty33", CR1, ALLDELAY, 0, 0 },
173    { "tty37", FF1 + CR2 + TAB1 + NL1, ALLDELAY, 0, 0 },
174    { "vt05", NL2, ALLDELAY, 0, 0 },
175
176    /* jmason modes and synonyms: */
177    { "evenp", EVENP, 0, 0, 0 },
178    { "-evenp", 0, EVENP, 0, 0 },
179    { "parity", EVENP, 0, 0, 0 },
180    { "-parity", 0, EVENP|ODDP, 0, 0 },
181    { "oddp", ODDP, 0, 0, 0 },
182    { "-oddp", 0, ODDP, 0, 0 },
183#ifdef LPASS8
184    { "pass8", 0, 0, LPASS8, 0 },
185    { "-pass8", 0, 0, 0, LPASS8, },
186#endif
187	{0}
188};
189
190
191 static struct special {
192    char *name;
193    char *cp;
194    char def;
195} special[] = {
196
197    { "stop", &termctrl.t_stopc, CSTOP },
198    { "start", &termctrl.t_startc, CSTART },
199    { 0, 0, 0 }
200};
201
202void Do_stty( int fd )
203{
204	int i, count;
205	int localmode;
206	int linedisc;
207	char *arg, *option;
208	struct line_list l;
209
210	Init_line_list(&l);
211	Split(&l,Stty_command_DYN,Whitespace,0,0,0,0,0,0);
212	Check_max(&l,1);
213	l.list[l.count] = 0;
214	DEBUG3("Do_stty: using SGTTYB, fd %d", fd );
215	if( ioctl( fd, TIOCGETP, &mode) < 0
216		|| ioctl( fd, TIOCGETC, &termctrl) < 0
217		|| ioctl( fd, TIOCLGET, &localmode) < 0
218		|| ioctl( fd, TIOCGLTC, &linectrl) < 0 ){
219		LOGERR_DIE(LOG_INFO) "cannot get tty parameters");
220	}
221	DEBUG2("stty: before mode 0x%x, lmode 0x%x, speed 0x%x",
222			 mode.sg_flags, localmode, mode.sg_ispeed);
223	if( Baud_rate_DYN ){
224		for( i = 0; bauds[i].baud && Baud_rate_DYN != bauds[i].baud; i++);
225		if( i == 0) {
226			FATAL(LOG_INFO) "illegal baud rate %d", Baud_rate_DYN );
227		}
228		mode.sg_ispeed = mode.sg_ospeed = bauds[i].speed;
229	}
230
231	for( count = 0; count < l.count; ++count ){
232		arg = l.list[count];
233		for( i = 0; modes[i].string && safestrcasecmp( modes[i].string, arg); i++);
234		if( modes[i].string ){
235			DEBUG3("stty: modes %s, mc 0x%x ms 0x%x lc 0x%x ls 0x%x",
236					 modes[i].string, modes[i].reset, modes[i].set,
237					 modes[i].lreset, modes[i].lset);
238			mode.sg_flags &= ~modes[i].reset;
239			mode.sg_flags |= modes[i].set;
240			localmode &= ~modes[i].lreset;
241			localmode |= modes[i].lset;
242			continue;
243		}
244		for( i = 0; special[i].name && safestrcasecmp( special[i].name, arg); i++);
245		if( special[i].name) {
246			++count;
247			option = l.list[count];
248			if( option == 0) {
249				FATAL(LOG_INFO) "stty: missing parameter for %s", arg);
250			}
251			if( option[0] == '^') {
252				if( option[1] == '?') {
253					*special[i].cp = 0177;
254				} else {
255					*special[i].cp = 037 & option[1];
256				}
257			} else {
258				*special[i].cp = option[0];
259			}
260			DEBUG3("stty: special %s %s", arg, option);
261			continue;
262		}
263		for( i = 0; bauds[i].string && safestrcasecmp( bauds[i].string, arg); i++);
264		if( bauds[i].string) {
265			DEBUG3("stty: speed %s", arg);
266			mode.sg_ispeed = mode.sg_ospeed = bauds[i].speed;
267			continue;
268		}
269		if( !safestrcasecmp( "new", arg)) {
270			DEBUG3("stty: ldisc %s", arg);
271			linedisc = NTTYDISC;
272			if( ioctl( fd, TIOCSETD, &linedisc) < 0)
273				LOGERR_DIE(LOG_INFO) "stty: TIOCSETD ioctl failed");
274			continue;
275		}
276		if( !safestrcasecmp( "old", arg)) {
277			DEBUG3("stty: ldisc %s", arg);
278			linedisc = 0;
279			if( ioctl( fd, TIOCSETD, &linedisc) < 0)
280				LOGERR_DIE(LOG_INFO) "stty: TIOCSETD ioctl failed");
281			continue;
282		}
283		FATAL(LOG_INFO) "unknown mode: %s\n", arg);
284	}
285	DEBUG2("stty: after mode 0x%x, lmode 0x%x, speed 0x%x",
286			 mode.sg_flags, localmode, mode.sg_ispeed);
287	if( ioctl( fd, TIOCSETN, &mode) < 0
288		|| ioctl( fd, TIOCSETC, &termctrl) < 0
289		|| ioctl( fd, TIOCSLTC, &linectrl) < 0
290		|| ioctl( fd, TIOCLSET, &localmode) < 0) {
291		LOGERR_DIE(LOG_NOTICE) "cannot set tty parameters");
292	}
293	Free_line_list(&l);
294}
295#endif
296
297#if USE_STTY == TERMIO
298
299/* the folks who are responsible for include files
300 * must be the lowest paid/motivated ones in
301 * OS development... (mj)
302 */
303
304#if !defined(TOSTOP) && defined(_TOSTOP)
305#define TOSTOP _TOSTOP
306#endif
307
308 static struct bauds {
309    char *string;
310    int baud;
311    int speed;
312}     bauds[] = {
313
314    { "110", 110, B110, },
315    { "134", 134, B134, },
316    { "150", 150, B150, },
317    { "300", 300, B300, },
318    { "600", 600, B600, },
319    { "1200", 1200, B1200, },
320    { "1800", 1800, B1800, },
321    { "2400", 2400, B2400, },
322    { "4800", 4800, B4800, },
323    { "9600", 9600, B9600, },
324    { "19200", 19200, B19200, },
325    { "38400", 38400, B38400, },
326#if defined(B57600)
327    { "57600", 57600, B57600, },
328#endif
329#if defined(B115200)
330    { "115200", 115200, B115200, },
331#endif
332#if defined(B230400)
333    { "230400", 230400, B230400, },
334#endif
335#if defined(B460800)
336    { "460800", 460800, B460800, },
337#endif
338#if defined(B500000)
339    { "500000", 500000, B500000, },
340#endif
341#if defined(B576000)
342    { "576000", 576000, B576000, },
343#endif
344#if defined(B921600)
345    { "921600", 921600, B921600, },
346#endif
347    { (char *) 0, 0, 0 }
348};
349
350 struct termio tio;
351 static struct {
352    char *string;
353    int iset;
354    int ireset;
355    int oset;
356    int oreset;
357    int cset;
358    int creset;
359    int lset;
360    int lreset;
361}      tmodes[] = {
362
363    /* input modes */
364    { "ignbrk", IGNBRK, 0, 0, 0, 0, 0, 0, 0 },
365    { "-ignbrk", 0, IGNBRK, 0, 0, 0, 0, 0, 0 },
366    { "brkint", BRKINT, 0, 0, 0, 0, 0, 0, 0 },
367    { "-brkint", 0, BRKINT, 0, 0, 0, 0, 0, 0 },
368    { "ignpar", IGNPAR, 0, 0, 0, 0, 0, 0, 0 },
369    { "-ignpar", 0, IGNPAR, 0, 0, 0, 0, 0, 0 },
370    { "parmrk", PARMRK, 0, 0, 0, 0, 0, 0, 0 },
371    { "-parmrk", 0, PARMRK, 0, 0, 0, 0, 0, 0 },
372    { "inpck", INPCK, 0, 0, 0, 0, 0, 0, 0 },
373    { "-inpck", 0, INPCK, 0, 0, 0, 0, 0, 0 },
374    { "istrip", ISTRIP, 0, 0, 0, 0, 0, 0, 0 },
375    { "-istrip", 0, ISTRIP, 0, 0, 0, 0, 0, 0 },
376    { "inlcr", INLCR, 0, 0, 0, 0, 0, 0, 0 },
377    { "-inlcr", 0, INLCR, 0, 0, 0, 0, 0, 0 },
378    { "igncr", IGNCR, 0, 0, 0, 0, 0, 0, 0 },
379    { "-igncr", 0, IGNCR, 0, 0, 0, 0, 0, 0 },
380    { "icrnl", ICRNL, 0, 0, 0, 0, 0, 0, 0 },
381    { "-icrnl", 0, ICRNL, 0, 0, 0, 0, 0, 0 },
382    { "lcase", IUCLC, 0, 0, 0, 0, 0, 0, 0 },
383    { "iuclc", IUCLC, 0, 0, 0, 0, 0, 0, 0 },
384    { "-lcase", 0, IUCLC, 0, 0, 0, 0, 0, 0 },
385    { "-iuclc", 0, IUCLC, 0, 0, 0, 0, 0, 0 },
386    { "ixon", IXON, 0, 0, 0, 0, 0, 0, 0 },
387    { "-ixon", 0, IXON, 0, 0, 0, 0, 0, 0 },
388    { "ixany", IXANY, 0, 0, 0, 0, 0, 0, 0 },
389    { "-ixany", 0, IXANY, 0, 0, 0, 0, 0, 0 },
390    { "ixoff", IXOFF, 0, 0, 0, 0, 0, 0, 0 },
391    { "-ixoff", 0, IXOFF, 0, 0, 0, 0, 0, 0 },
392    { "decctlq", IXANY, 0, 0, 0, 0, 0, 0, 0 },
393    { "-decctlq", 0, IXANY, 0, 0, 0, 0, 0, 0 },
394    { "tandem", IXOFF, 0, 0, 0, 0, 0, 0, 0 },
395    { "-tandem", 0, IXOFF, 0, 0, 0, 0, 0, 0 },
396#ifdef IMAXBEL
397    { "imaxbel", IMAXBEL, 0, 0, 0, 0, 0, 0, 0 },
398    { "-maxbel", 0, IMAXBEL, 0, 0, 0, 0, 0, 0 },
399#endif
400    /* output modes */
401    { "opost", 0, 0, OPOST, 0, 0, 0, 0, 0 },
402    { "-opost", 0, 0, 0, OPOST, 0, 0, 0, 0 },
403    { "olcuc", 0, 0, OLCUC, 0, 0, 0, 0, 0 },
404    { "-olcuc", 0, 0, 0, OLCUC, 0, 0, 0, 0 },
405    { "onlcr", 0, 0, ONLCR, 0, 0, 0, 0, 0 },
406    { "-onlcr", 0, 0, 0, ONLCR, 0, 0, 0, 0 },
407    { "ocrnl", 0, 0, OCRNL, 0, 0, 0, 0, 0 },
408    { "-ocrnl", 0, 0, 0, OCRNL, 0, 0, 0, 0 },
409    { "onocr", 0, 0, ONOCR, 0, 0, 0, 0, 0 },
410    { "-onocr", 0, 0, 0, ONOCR, 0, 0, 0, 0 },
411    { "onlret", 0, 0, ONLRET, 0, 0, 0, 0, 0 },
412    { "-onlret", 0, 0, 0, ONLRET, 0, 0, 0, 0 },
413    { "ofill", 0, 0, OFILL, 0, 0, 0, 0, 0 },
414    { "-ofill", 0, 0, 0, OFILL, 0, 0, 0, 0 },
415    { "ofdel", 0, 0, OFDEL, 0, 0, 0, 0, 0 },
416    { "-ofdel", 0, 0, 0, OFDEL, 0, 0, 0, 0 },
417    { "nl0", 0, 0, NL0, NLDLY, 0, 0, 0, 0 },
418    { "nl1", 0, 0, NL1, NLDLY, 0, 0, 0, 0 },
419    { "cr0", 0, 0, CR1, CRDLY, 0, 0, 0, 0 },
420    { "cr1", 0, 0, CR1, CRDLY, 0, 0, 0, 0 },
421    { "cr2", 0, 0, CR2, CRDLY, 0, 0, 0, 0 },
422    { "cr3", 0, 0, CR3, CRDLY, 0, 0, 0, 0 },
423    { "tab0", 0, 0, TAB0, TABDLY, 0, 0, 0, 0 },
424    { "tab1", 0, 0, TAB1, TABDLY, 0, 0, 0, 0 },
425    { "tab2", 0, 0, TAB2, TABDLY, 0, 0, 0, 0 },
426    { "tab3", 0, 0, TAB3, TABDLY, 0, 0, 0, 0 },
427    { "bs0", 0, 0, BS0, BSDLY, 0, 0, 0, 0 },
428    { "bs1", 0, 0, BS1, BSDLY, 0, 0, 0, 0 },
429    { "vt0", 0, 0, VT0, VTDLY, 0, 0, 0, 0 },
430    { "vt1", 0, 0, VT1, VTDLY, 0, 0, 0, 0 },
431    { "ff0", 0, 0, FF0, FFDLY, 0, 0, 0, 0 },
432    { "ff1", 0, 0, FF1, FFDLY, 0, 0, 0, 0 },
433    { "nopost", 0, 0, 0, OPOST, 0, 0, 0, 0 },
434    { "-nopost", 0, 0, OPOST, 0, 0, 0, 0, 0 },
435    { "fill", 0, 0, OFILL, OFDEL, 0, 0, 0, 0 },
436    { "-fill", 0, 0, 0, OFILL | OFDEL, 0, 0, 0, 0 },
437    { "nul-fill", 0, 0, OFILL, OFDEL, 0, 0, 0, 0 },
438    { "del-fill", 0, 0, OFILL | OFDEL, 0, 0, 0, 0, 0 },
439#ifdef XTABS
440    { "tabs", 0, 0, 0, XTABS | TABDLY, 0, 0, 0, 0 },
441    { "-tabs", 0, 0, XTABS, TABDLY, 0, 0, 0, 0 },
442#endif
443    /* control modes */
444    { "cs5", 0, 0, 0, 0, CS5, CSIZE, 0, 0 },
445    { "cs6", 0, 0, 0, 0, CS6, CSIZE, 0, 0 },
446    { "cs7", 0, 0, 0, 0, CS7, CSIZE, 0, 0 },
447    { "cs8", 0, 0, 0, 0, CS8, CSIZE, 0, 0 },
448    { "cstopb", 0, 0, 0, 0, CSTOPB, 0, 0, 0 },
449    { "-cstopb", 0, 0, 0, 0, 0, CSTOPB, 0, 0 },
450    { "cread", 0, 0, 0, 0, CREAD, 0, 0, 0 },
451    { "-cread", 0, 0, 0, 0, 0, CREAD, 0, 0 },
452    { "parenb", 0, 0, 0, 0, PARENB, 0, 0, 0 },
453    { "-parenb", 0, 0, 0, 0, 0, PARENB, 0, 0 },
454    { "parodd", 0, 0, 0, 0, PARODD, 0, 0, 0 },
455    { "-parodd", 0, 0, 0, 0, 0, PARODD, 0, 0 },
456    { "hupcl", 0, 0, 0, 0, HUPCL, 0, 0, 0 },
457    { "-hupcl", 0, 0, 0, 0, 0, HUPCL, 0, 0 },
458    { "clocal", 0, 0, 0, 0, CLOCAL, 0, 0, 0 },
459    { "-clocal", 0, 0, 0, 0, 0, CLOCAL, 0, 0 },
460#ifdef LOBLK
461    { "loblk", 0, 0, 0, 0, LOBLK, 0, 0, 0 },
462    { "-loblk", 0, 0, 0, 0, 0, LOBLK, 0, 0 },
463#endif
464    { "parity", 0, 0, 0, 0, PARENB | CS7, PARODD | CSIZE, 0, 0 },
465    { "-parity", 0, 0, 0, 0, CS8, PARENB | CSIZE, 0, 0 },
466    { "evenp", 0, 0, 0, 0, PARENB | CS7, PARODD | CSIZE, 0, 0 },
467    { "-evenp", 0, 0, 0, 0, CS8, PARENB | CSIZE, 0, 0 },
468    { "oddp", 0, 0, 0, 0, PARENB | PARODD | CS7, CSIZE, 0, 0 },
469    { "-oddp", 0, 0, 0, 0, CS8, PARENB | PARODD | CSIZE, 0, 0 },
470    { "stopb", 0, 0, 0, 0, CSTOPB, 0, 0, 0 },
471    { "-stopb", 0, 0, 0, 0, 0, CSTOPB, 0, 0 },
472    { "hup", 0, 0, 0, 0, HUPCL, 0, 0, 0 },
473    { "-hup", 0, 0, 0, 0, 0, HUPCL, 0, 0 },
474#ifdef CRTSCTS
475    { "crtscts", 0, 0, 0, 0, CRTSCTS, 0, 0, 0 },
476    { "-crtscts", 0, 0, 0, 0, 0, CRTSCTS, 0, 0 },
477#endif
478    /* local modes */
479    { "isig", 0, 0, 0, 0, 0, 0, ISIG, 0 },
480    { "-isig", 0, 0, 0, 0, 0, 0, 0, ISIG },
481    { "noisig", 0, 0, 0, 0, 0, 0, 0, ISIG },
482    { "-noisig", 0, 0, 0, 0, 0, 0, ISIG, 0 },
483    { "icanon", 0, 0, 0, 0, 0, 0, ICANON, 0 },
484    { "-icanon", 0, 0, 0, 0, 0, 0, 0, ICANON },
485    { "cbreak", 0, 0, 0, 0, 0, 0, ICANON, 0 },
486    { "-cbreak", 0, 0, 0, 0, 0, 0, 0, ICANON },
487    { "xcase", 0, 0, 0, 0, 0, 0, XCASE, 0 },
488    { "-xcase", 0, 0, 0, 0, 0, 0, 0, XCASE },
489    { "echo", 0, 0, 0, 0, 0, 0, ECHO, 0 },
490    { "-echo", 0, 0, 0, 0, 0, 0, 0, ECHO },
491    { "echoe", 0, 0, 0, 0, 0, 0, ECHOE, 0 },
492    { "-echoe", 0, 0, 0, 0, 0, 0, 0, ECHOE },
493    { "crterase", 0, 0, 0, 0, 0, 0, ECHOE, 0 },
494    { "-crterase", 0, 0, 0, 0, 0, 0, 0, ECHOE },
495    { "echok", 0, 0, 0, 0, 0, 0, ECHOK, 0 },
496    { "-echok", 0, 0, 0, 0, 0, 0, 0, ECHOK },
497    { "lfkc", 0, 0, 0, 0, 0, 0, ECHOK, 0 },
498    { "-lfkc", 0, 0, 0, 0, 0, 0, 0, ECHOK },
499    { "echonl", 0, 0, 0, 0, 0, 0, ECHONL, 0 },
500    { "-echonl", 0, 0, 0, 0, 0, 0, 0, ECHONL },
501    { "noflsh", 0, 0, 0, 0, 0, 0, NOFLSH, 0 },
502    { "-noflsh", 0, 0, 0, 0, 0, 0, 0, NOFLSH },
503    { "tostop", 0, 0, 0, 0, 0, 0, TOSTOP, 0 },
504    { "-tostop", 0, 0, 0, 0, 0, 0, 0, TOSTOP },
505#ifdef ECHOCTL
506    { "echoctl", 0, 0, 0, 0, 0, 0, ECHOCTL, 0 },
507    { "-echoctl", 0, 0, 0, 0, 0, 0, 0, ECHOCTL },
508    { "ctlecho", 0, 0, 0, 0, 0, 0, ECHOCTL, 0 },
509    { "-ctlecho", 0, 0, 0, 0, 0, 0, 0, ECHOCTL },
510#endif
511#ifdef ECHOPRT
512    { "echoprt", 0, 0, 0, 0, 0, 0, ECHOPRT, 0 },
513    { "-echoprt", 0, 0, 0, 0, 0, 0, 0, ECHOPRT },
514    { "prterase", 0, 0, 0, 0, 0, 0, ECHOPRT, 0 },
515    { "-prterase", 0, 0, 0, 0, 0, 0, 0, ECHOPRT },
516#endif
517#ifdef ECHOKE
518    { "echoke", 0, 0, 0, 0, 0, 0, ECHOKE, 0 },
519    { "-echoke", 0, 0, 0, 0, 0, 0, 0, ECHOKE },
520    { "crtkill", 0, 0, 0, 0, 0, 0, ECHOKE, 0 },
521    { "-crtkill", 0, 0, 0, 0, 0, 0, 0, ECHOKE },
522#endif
523    /* convenience modes */
524    { "lcase", IUCLC, 0, OLCUC, 0, 0, 0, XCASE, 0 },
525    { "-lcase", 0, IUCLC, 0, OLCUC, 0, 0, 0, XCASE },
526    { "nl", 0, ICRNL, 0, ONLCR, 0, 0, 0, 0 },
527    { "-nl", ICRNL, INLCR | IGNCR, ONLCR, OCRNL | ONLRET, 0, 0, 0, 0 },
528    { "litout", 0, 0, OPOST, 0, CS8, CSIZE | PARENB, 0, 0 },
529    { "-litout", 0, 0, 0, OPOST, CS7 | PARENB, CSIZE, 0, 0 },
530    { "pass8", 0, ISTRIP, 0, 0, CS8, CSIZE | PARENB, 0, 0 },
531    { "-pass8", ISTRIP, 0, 0, 0, CS7 | PARENB, CSIZE, 0, 0 },
532    { "raw", 0, -1, 0, OPOST, CS8, CSIZE | PARENB, 0, ISIG | ICANON | XCASE,
533    },
534#ifdef IMAXBEL
535    { "-raw", BRKINT | IGNPAR | ISTRIP | ICRNL | IXON | IMAXBEL,
536                0, OPOST, 0, CS7 | PARENB, CSIZE, ISIG | ICANON, 0 },
537    { "sane", BRKINT | IGNPAR | ISTRIP | ICRNL | IXON | IMAXBEL,
538                IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC | IXOFF,
539                OPOST | ONLCR,
540                OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL | NLDLY | CRDLY|
541                TABDLY | BSDLY | VTDLY | FFDLY,
542                CS7 | PARENB | CREAD, CSIZE | PARODD | CLOCAL,
543                ISIG | ICANON | ECHO | ECHOK, XCASE | ECHOE | ECHONL | NOFLSH},
544#endif                          /* IMAXBEL */
545    { "cooked", BRKINT | IGNPAR | ISTRIP | ICRNL | IXON, 0, OPOST, 0,
546                CS7 | PARENB, CSIZE, ISIG | ICANON, 0 },
547    {0},
548};
549
550void Do_stty( int fd )
551{
552	int i, count;
553	char *arg;
554	struct line_list l;
555
556	Init_line_list(&l);
557	Split(&l,Stty_command_DYN,Whitespace,0,0,0,0,0,0);
558	Check_max(&l,1);
559	l.list[l.count] = 0;
560
561	DEBUG3("Do_stty: using TERMIO, fd %d", fd );
562	if( ioctl( fd, TCGETA, &tio) < 0) {
563		LOGERR_DIE(LOG_INFO) "cannot get tty parameters");
564	}
565	DEBUG2("stty: before imode 0x%x, omode 0x%x, cmode 0x%x, lmode 0x%x",
566			 tio.c_iflag, tio.c_oflag, tio.c_cflag, tio.c_lflag);
567
568	if( Baud_rate_DYN ){
569		for( i = 0; bauds[i].baud && Baud_rate_DYN != bauds[i].baud; i++);
570		if( i == 0) {
571			FATAL(LOG_INFO) "illegal baud rate %d", Baud_rate_DYN);
572		}
573		tio.c_cflag &= ~CBAUD;
574		tio.c_cflag |= bauds[i].speed;
575	}
576	for( count = 0; count < l.count; ++count ){
577		arg = l.list[count];
578		for( i = 0;
579			tmodes[i].string && safestrcasecmp( tmodes[i].string, arg); i++);
580
581		if( tmodes[i].string) {
582			DEBUG3("stty: modes %s, ic 0x%x is 0x%x oc 0x%x os 0x%x cc 0x%x cs 0x%x lc 0x%x ls 0x%x",
583					 tmodes[i].string, tmodes[i].ireset, tmodes[i].iset,
584					 tmodes[i].oreset, tmodes[i].oset, tmodes[i].creset, tmodes[i].cset,
585					 tmodes[i].lreset, tmodes[i].lset);
586
587			tio.c_iflag &= ~tmodes[i].ireset;
588			tio.c_iflag |= tmodes[i].iset;
589			tio.c_oflag &= ~tmodes[i].oreset;
590			tio.c_oflag |= tmodes[i].oset;
591			tio.c_cflag &= ~tmodes[i].creset;
592			tio.c_cflag |= tmodes[i].cset;
593			tio.c_lflag &= ~tmodes[i].lreset;
594			tio.c_lflag |= tmodes[i].lset;
595			continue;
596		}
597		for( i = 0; bauds[i].string && safestrcasecmp( bauds[i].string, arg); i++);
598		if( bauds[i].string) {
599			DEBUG3("stty: speed %s", arg);
600			tio.c_cflag &= ~CBAUD;
601			tio.c_cflag |= bauds[i].speed;
602			continue;
603		}
604		FATAL(LOG_INFO) "unknown mode: %s\n", arg);
605	}
606
607	if( Read_write_DYN && (tio.c_cflag & ICANON) == 0) {
608		/* VMIN & VTIME: suggested by Michael Joosten
609		 * only do this if ICANON is off -- Martin Forssen
610		 */
611		DEBUG2("setting port to read/write with unbuffered reads");
612		tio.c_cc[VMIN] = 1;
613		tio.c_cc[VTIME] = 0;
614	}
615	DEBUG2("stty: before imode 0x%x, omode 0x%x, cmode 0x%x, lmode 0x%x",
616			 tio.c_iflag, tio.c_oflag, tio.c_cflag, tio.c_lflag);
617	if( ioctl( fd, TCSETA, &tio) < 0) {
618		LOGERR_DIE(LOG_NOTICE) "cannot set tty parameters");
619	}
620	Free_line_list(&l);
621}
622#endif
623
624#if USE_STTY == TERMIOS
625
626#ifndef HAVE_TCSETATTR
627#define tcgetattr(fd,tdat)		(ioctl( (fd), TCGETS, (tdat)))
628#define tcsetattr(fd,flags,tdat)	(ioctl( (fd), TCSETS, (tdat)))
629					/* ignore the flags arg. */
630#endif
631
632 static struct bauds {
633	char *string;
634	int baud;
635	int speed;
636}     bauds[] = {
637
638	{ "B50", 50, B50, }, { "50", 50, B50, },
639	{ "B75", 75, B75, }, { "75", 75, B75, },
640	{ "B110", 110, B110, }, { "110", 110, B110, },
641	{ "B134", 134, B134, }, { "134", 134, B134, },
642	{ "B150", 150, B150, }, { "150", 150, B150, },
643	{ "B300", 300, B300, }, { "300", 300, B300, },
644	{ "B600", 600, B600, }, { "600", 600, B600, },
645	{ "B1200", 1200, B1200, }, { "1200", 1200, B1200, },
646	{ "B1800", 1800, B1800, }, { "1800", 1800, B1800, },
647	{ "B2400", 2400, B2400, }, { "2400", 2400, B2400, },
648	{ "B4800", 4800, B4800, }, { "4800", 4800, B4800, },
649	{ "B9600", 9600, B9600, }, { "9600", 9600, B9600, },
650	{ "B19200", 19200, B19200, }, { "19200", 19200, B19200, },
651	{ "B38400", 38400, B38400, }, { "38400", 38400, B38400, },
652#ifdef EXTA
653	{"EXTA", EXTA, EXTA},
654	{"EXTB", EXTB, EXTB},
655#endif
656#if defined(B57600)
657    { "57600", 57600, B57600, }, { "B57600", 57600, B57600, },
658#endif
659#if defined(B115200)
660    { "115200", 115200, B115200, }, { "B115200", 115200, B115200, },
661#endif
662#if defined(B230400)
663    { "230400", 230400, B230400, }, { "B230400", 230400, B230400, },
664#endif
665#if defined(B460800)
666    { "460800", 460800, B460800, }, { "B460800", 460800, B460800, },
667#endif
668#if defined(B500000)
669    { "500000", 500000, B500000, }, { "B500000", 500000, B500000, },
670#endif
671#if defined(B576000)
672    { "576000", 576000, B576000, }, { "B576000", 576000, B576000, },
673#endif
674#if defined(B921600)
675    { "921600", 921600, B921600, }, { "B921600", 921600, B921600, },
676#endif
677	{ (char *) 0, 0, 0 }
678};
679
680 struct s_term_dat {
681	char *name;
682	uint or_dat;
683	uint and_dat;
684};
685
686#undef FLAGS
687#ifndef _UNPROTO_
688#define FLAGS(X) { #X, X , 0 }, { "-" #X, 0, X }
689#else
690#define __string(X) "X"
691#define FLAGS(X) { __string(X), X , 0 }, { "-" __string(X), 0, X }
692#endif
693
694
695
696/* c_iflag bits */
697 static struct s_term_dat c_i_dat[] =
698{
699	FLAGS(IGNBRK),
700	FLAGS(BRKINT),
701	FLAGS(IGNPAR),
702	FLAGS(PARMRK),
703	FLAGS(INPCK),
704	FLAGS(ISTRIP),
705	FLAGS(INLCR),
706	FLAGS(IGNCR),
707	FLAGS(ICRNL),
708#ifdef IUCLC
709	FLAGS(IUCLC),
710 	{"lcase", IUCLC, 0}, {"-lcase", 0, IUCLC },
711#endif
712	FLAGS(IXON),
713	FLAGS(IXANY),
714	FLAGS(IXOFF),
715
716#ifdef IMAXBEL
717	FLAGS(IMAXBEL),
718#else
719	/* work out what they do and simulate with IFLAGONE|IFLAGTWO */
720#endif
721
722	/* jmason addition: */
723 	{"PASS8", 0, ISTRIP}, {"-PASS8", ISTRIP, 0},
724	{0, 0, 0}
725};
726
727/* c_oflag bits */
728 static struct s_term_dat c_o_dat[] =
729{
730	FLAGS(OPOST),
731#ifdef OLCUC
732	FLAGS(OLCUC),
733#endif
734#ifdef ONLCR
735	FLAGS(ONLCR),
736 	{"crmod", ONLCR, 0}, {"-crmod", 0, ONLCR},
737#endif
738#ifdef OCRNL
739	FLAGS(OCRNL),
740#endif
741#ifdef ONOCR
742	FLAGS(ONOCR),
743#endif
744#ifdef ONLRET
745	FLAGS(ONLRET),
746#endif
747#ifdef OFILL
748	FLAGS(OFILL),
749#endif
750#ifdef OFDEL
751	FLAGS(OFDEL),
752#endif
753#ifdef NLDLY
754	{"NL0", 0, NLDLY},
755	{"NL1", NL1, NLDLY},
756#endif
757#ifdef CRDLY
758	{"CR0", CR0, CRDLY},
759	{"CR1", CR1, CRDLY},
760	{"CR2", CR2, CRDLY},
761	{"CR3", CR3, CRDLY},
762#endif
763#ifdef TABDLY
764	{"TAB0", TAB0, TABDLY},
765	{"TAB1", TAB1, TABDLY},
766	{"TAB2", TAB2, TABDLY},
767	{"TAB3", TAB3, TABDLY},
768#endif
769#ifdef BSDLY
770	{"BS0", BS0, BSDLY},
771	{"BS1", BS1, BSDLY},
772#endif
773#ifdef VTDLY
774	{"VT0", VT0, VTDLY},
775	{"VT1", VT1, VTDLY},
776#endif
777#ifdef FFDLY
778	{"FF0", FF0, FFDLY},
779	{"FF1", FF1, FFDLY},
780#endif
781
782	/* jmason addition: */
783#ifdef TABDLY
784	{"TABS", TAB3, TABDLY},
785#endif
786	{0, 0, 0}
787};
788
789/* c_cflag bit meaning */
790 static struct s_term_dat c_c_dat[] =
791{
792	{"CS5", CS5, CSIZE},
793	{"CS6", CS6, CSIZE},
794	{"CS7", CS7, CSIZE},
795	{"CS8", CS8, CSIZE},
796	{"CSTOPB", CSTOPB, 0},
797	{"-CSTOPB", 0, CSTOPB},
798	{"CREAD", CREAD, 0},
799	{"-CREAD", 0, CREAD},
800	{"PARENB", PARENB, 0},
801	{"-PARENB", 0, PARENB},
802	{"PARODD", PARODD, 0},
803	{"-PARODD", 0, PARODD},
804	{"HUPCL", HUPCL, 0},
805	{"-HUPCL", 0, HUPCL},
806	{"CLOCAL", CLOCAL, 0},
807	{"-CLOCAL", 0, CLOCAL},
808
809#ifdef CRTSCTS
810	/* work out what they do and simulate with IFLAGONE|IFLAGTWO */
811	{"CRTSCTS", CRTSCTS, 0},
812	{"-CRTSCTS", 0, CRTSCTS},
813#endif
814
815	/* jmason additions, from SunOS stty(1v) combination modes: */
816	{"even", PARENB | CS7, PARODD | CSIZE},
817	{"-even", CS8, PARENB | CSIZE},
818	{"EVENP", PARENB | CS7, PARODD | CSIZE},
819	{"-EVENP", CS8, PARENB | CSIZE},
820	{"PARITY", PARENB | CS7, PARODD | CSIZE},
821	{"-PARITY", CS8, PARENB | CSIZE},
822	{"odd", PARODD| PARENB | CS7, CSIZE},
823	{"-odd", CS8, PARENB | PARODD | CSIZE},
824	{"ODDP", PARODD | PARENB | CS7, CSIZE},
825	{"-ODDP", CS8, PARENB | PARODD | CSIZE},
826	{"PASS8", CS8, PARENB | CSIZE},
827	{"-PASS8", PARENB | CS7, CSIZE},
828	{0, 0, 0}
829};
830
831/* c_lflag bits */
832 static struct s_term_dat c_l_dat[] =
833{
834	{"ISIG", ISIG, 0},
835	{"-ISIG", 0, ISIG},
836	{"cooked", ICANON, 0},
837	{"-raw", ICANON, 0},
838	{"cbreak", ICANON, 0},
839	{"ICANON", ICANON, 0},
840	{"-ICANON", 0, ICANON},
841	{"raw", 0, ICANON},
842	{"-cooked", 0, ICANON},
843#ifdef XCASE
844	{"XCASE", XCASE, 0},
845	{"-XCASE", 0, XCASE},
846#endif
847	{"ECHO", ECHO, 0},
848	{"-ECHO", 0, ECHO},
849	{"ECHOE", ECHOE, 0},
850	{"-ECHOE", 0, ECHOE},
851	{"ECHOK", ECHOK, 0},
852	{"-ECHOK", 0, ECHOK},
853	{"ECHONL", ECHONL, 0},
854	{"-ECHONL", 0, ECHONL},
855	{"NOFLSH", NOFLSH, 0},
856	{"-NOFLSH", 0, NOFLSH},
857	{"TOSTOP", TOSTOP, 0},
858	{"-TOSTOP", 0, TOSTOP},
859	{"IEXTEN", IEXTEN, 0},
860	{"-IEXTEN", 0, IEXTEN},
861
862#ifdef ECHOCTL
863	{"ECHOCTL", ECHOCTL, 0},
864	{"-ECHOCTL", 0, ECHOCTL},
865	{"CTLECHO", ECHOCTL, 0},
866	{"-CTLECHO", 0, ECHOCTL},
867#else
868	/* work out what they do and simulate with IFLAGONE|IFLAGTWO */
869#endif
870#ifdef ECHOPRT
871	{"ECHOPRT", ECHOPRT, 0},
872	{"-ECHOPRT", 0, ECHOPRT},
873	{"PRTERASE", ECHOPRT, 0},
874	{"-PRTERASE", 0, ECHOPRT},
875	/* ditto etc. -- you get the story */
876#endif
877#ifdef ECHOKE
878	{"ECHOKE", ECHOKE, 0},
879	{"-ECHOKE", 0, ECHOKE},
880	{"CRTKILL", ECHOKE, 0},
881	{"-CRTKILL", 0, ECHOKE},
882#endif
883#ifdef FLUSHO
884	{"FLUSHO", FLUSHO, 0},
885	{"-FLUSHO", 0, FLUSHO},
886#endif
887#ifdef PENDIN
888	{"PENDIN", PENDIN, 0},
889	{"-PENDIN", 0, PENDIN},
890#endif
891	{ 0 ,0 ,0 }
892};
893
894#ifdef USE_TERMIOX
895/* termiox bits */
896 static struct s_term_dat tx_x_dat[] =
897{
898	{"RTSXOFF", RTSXOFF, 0},
899	{"-RTSXOFF", 0, RTSXOFF},
900	{"CTSXON", CTSXON, 0},
901	{"-CTSXON", 0, CTSXON}
902};
903
904 struct termiox tx_dat;
905#endif /* USE_TERMIOX */
906
907 struct termios t_dat;
908
909 static struct special {
910	char *name;
911	char *cp;
912}       special[] = {
913
914	{ "stop", (char *)&(t_dat.c_cc[VSTOP]) },
915	{ "start", (char *)&(t_dat.c_cc[VSTART]) },
916	{ 0, 0 }
917};
918
919void Do_stty( int fd )
920{
921#ifdef USE_TERMIOX
922	int termiox_fail = 0;
923#endif
924	int i,count;
925	char *arg, *option;
926	struct line_list l;
927
928	Init_line_list(&l);
929	Split(&l,Stty_command_DYN,Whitespace,0,0,0,0,0,0);
930	Check_max(&l,1);
931	l.list[l.count] = 0;
932
933	DEBUG3("Do_stty: using TERMIOS, fd %d", fd );
934	if( tcgetattr( fd, &t_dat) < 0 ){
935		LOGERR_DIE(LOG_INFO) "cannot get tty parameters");
936	}
937#ifdef USE_TERMIOX
938	if( ioctl( fd, TCGETX, &tx_dat) < 0 ){
939		DEBUG1("stty: TCGETX failed");
940		termiox_fail = 1;
941	}
942#endif
943	DEBUG2("stty: before iflag 0x%x, oflag 0x%x, cflag 0x%x lflag 0x%x",
944			 (int)t_dat.c_iflag, (int)t_dat.c_oflag,
945			(int)t_dat.c_cflag, (int)t_dat.c_lflag);
946	if( Baud_rate_DYN ){
947		for( i = 0; bauds[i].baud && Baud_rate_DYN != bauds[i].baud; i++);
948		if( i == 0 ){
949			FATAL(LOG_INFO) "illegal baud rate %d", Baud_rate_DYN );
950		}
951		DEBUG2("stty: before baudrate : cflag 0x%x",(int)t_dat.c_cflag);
952
953#ifdef HAVE_CFSETISPEED
954		DEBUG2("Do_stty: using cfsetispeed/cfsetospeed");
955		/* POSIX baudrate manipulation */
956		cfsetispeed( &t_dat, bauds[i].speed);
957		cfsetospeed( &t_dat, bauds[i].speed);
958#else
959		DEBUG2("Do_stty: setting tdat.c_cflag");
960		t_dat.c_cflag &= ~CBAUD;
961		t_dat.c_cflag |= bauds[i].speed;
962#endif
963
964		DEBUG2("stty: after baudrate : cflag 0x%x",(int)t_dat.c_cflag);
965	}
966
967	for( count = 0; count < l.count; ++count ){
968		arg = l.list[count];
969		for( i = 0; bauds[i].string && safestrcasecmp( bauds[i].string, arg); i++);
970
971		if( bauds[i].string ){
972#ifdef HAVE_CFSETISPEED
973			DEBUG2("Do_stty: using cfsetispeed/cfsetospeed");
974			/* POSIX baudrate manipulation */
975			cfsetispeed( &t_dat, bauds[i].speed);
976			cfsetospeed( &t_dat, bauds[i].speed);
977#else
978			DEBUG2("Do_stty: setting tdat.c_cflag");
979			t_dat.c_cflag &= ~CBAUD;
980			t_dat.c_cflag |= bauds[i].speed;
981#endif
982			continue;
983		}
984		for( i = 0; c_i_dat[i].name && safestrcasecmp( c_i_dat[i].name, arg); i++);
985		if( c_i_dat[i].name ){
986			DEBUG3("stty: c_iflag %s, ms 0x%x mc 0x%x",
987					 c_i_dat[i].name, c_i_dat[i].or_dat, c_i_dat[i].and_dat);
988			t_dat.c_iflag &= ~(c_i_dat[i].and_dat);
989			t_dat.c_iflag |= c_i_dat[i].or_dat;
990			continue;
991		}
992		for( i = 0; c_o_dat[i].name && safestrcasecmp( c_o_dat[i].name, arg); i++);
993		if( c_o_dat[i].name ){
994			DEBUG3("stty: c_oflag %s, ms 0x%x mc 0x%x",
995					 c_o_dat[i].name, c_o_dat[i].or_dat, c_o_dat[i].and_dat);
996			t_dat.c_oflag &= ~(c_o_dat[i].and_dat);
997			t_dat.c_oflag |= c_o_dat[i].or_dat;
998			continue;
999		}
1000		for( i = 0; c_c_dat[i].name && safestrcasecmp( c_c_dat[i].name, arg); i++);
1001		if( c_c_dat[i].name ){
1002			DEBUG3("stty: c_cflag %s, ms 0x%x mc 0x%x",
1003					 c_c_dat[i].name, c_c_dat[i].or_dat, c_c_dat[i].and_dat);
1004			t_dat.c_cflag &= ~(c_c_dat[i].and_dat);
1005			t_dat.c_cflag |= c_c_dat[i].or_dat;
1006			continue;
1007		}
1008		for( i = 0; c_l_dat[i].name && safestrcasecmp( c_l_dat[i].name, arg); i++);
1009		if( c_l_dat[i].name ){
1010			DEBUG3("stty: c_lflag %s, ms 0x%x mc 0x%x",
1011					 c_l_dat[i].name, c_l_dat[i].or_dat, c_l_dat[i].and_dat);
1012			t_dat.c_lflag &= ~(c_l_dat[i].and_dat);
1013			t_dat.c_lflag |= c_l_dat[i].or_dat;
1014			continue;
1015		}
1016		for( i = 0; special[i].name && safestrcasecmp( special[i].name, arg); i++);
1017		if( special[i].name ){
1018			++count;
1019			option = l.list[count];
1020			if( option == 0 ){
1021				FATAL(LOG_INFO) "stty: missing parameter for %s", arg);
1022			}
1023			if( option[0] == '^' ){
1024				if( option[1] == '?' ){
1025					*special[i].cp = 0177;
1026				} else {
1027					*special[i].cp = 037 & option[1];
1028				}
1029			} else {
1030				*special[i].cp = option[0];
1031			}
1032			DEBUG3("stty: special %s %s", arg, option);
1033			continue;
1034		}
1035#ifdef USE_TERMIOX
1036		for( i = 0; tx_x_dat[i].name && safestrcasecmp( tx_x_dat[i].name, arg); i++);
1037		if( tx_x_dat[i].name ){
1038			DEBUG3("stty: tx_xflag %s, ms 0x%x mc 0x%x",
1039					 tx_x_dat[i].name, tx_x_dat[i].or_dat, tx_x_dat[i].and_dat);
1040			tx_dat.x_hflag &= ~(tx_x_dat[i].and_dat);
1041			tx_dat.x_hflag |= tx_x_dat[i].or_dat;
1042			continue;
1043		}
1044#endif /* USE_TERMIOX */
1045		FATAL(LOG_INFO) "unknown mode: %s\n", arg);
1046	}
1047
1048	if( Read_write_DYN && (t_dat.c_lflag & ICANON) == 0 ){
1049		/* only do this if ICANON is off -- Martin Forssen */
1050		DEBUG2("setting port to read/write with unbuffered reads( MIN=1, TIME=0)");
1051		t_dat.c_cc[VMIN] = 1;
1052		t_dat.c_cc[VTIME] = 0;
1053	}
1054	DEBUG2("stty: after iflag 0x%x, oflag 0x%x, cflag 0x%x lflag 0x%x",
1055		(int)t_dat.c_iflag, (int)t_dat.c_oflag,
1056		(int)t_dat.c_cflag, (int)t_dat.c_lflag);
1057
1058	if( tcsetattr( fd, TCSANOW, &t_dat) < 0 ){
1059		LOGERR_DIE(LOG_NOTICE) "cannot set tty parameters");
1060	}
1061
1062#ifdef USE_TERMIOX
1063	if( termiox_fail == 0 && ioctl( fd, TCSETX, &tx_dat) < 0 ){
1064		LOGERR_DIE(LOG_NOTICE) "cannot set tty parameters (termiox)");
1065	}
1066#endif
1067	Free_line_list(&l);
1068}
1069#endif
1070