1/****************************************************************************
2 * Copyright 2020 Thomas E. Dickey                                          *
3 * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
4 *                                                                          *
5 * Permission is hereby granted, free of charge, to any person obtaining a  *
6 * copy of this software and associated documentation files (the            *
7 * "Software"), to deal in the Software without restriction, including      *
8 * without limitation the rights to use, copy, modify, merge, publish,      *
9 * distribute, distribute with modifications, sublicense, and/or sell       *
10 * copies of the Software, and to permit persons to whom the Software is    *
11 * furnished to do so, subject to the following conditions:                 *
12 *                                                                          *
13 * The above copyright notice and this permission notice shall be included  *
14 * in all copies or substantial portions of the Software.                   *
15 *                                                                          *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23 *                                                                          *
24 * Except as contained in this notice, the name(s) of the above copyright   *
25 * holders shall not be used in advertising or otherwise to promote the     *
26 * sale, use or other dealings in this Software without prior written       *
27 * authorization.                                                           *
28 ****************************************************************************/
29
30/****************************************************************************
31 *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32 *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
33 *     and: Thomas E. Dickey                        1996-on                 *
34 ****************************************************************************/
35
36/*
37 *	lib_baudrate.c
38 *
39 */
40
41#include <curses.priv.h>
42#include <termcap.h>		/* ospeed */
43#if defined(__FreeBSD__) || defined(__OpenBSD__)
44#include <sys/param.h>
45#endif
46
47/*
48 * These systems use similar header files, which define B1200 as 1200, etc.,
49 * but can be overridden by defining USE_OLD_TTY so B1200 is 9, which makes all
50 * of the indices up to B115200 fit nicely in a 'short', allowing us to retain
51 * ospeed's type for compatibility.
52 */
53#if NCURSES_OSPEED_COMPAT && \
54 	((defined(__FreeBSD__) && (__FreeBSD_version < 700000)) || \
55	defined(__NetBSD__) || \
56	((defined(__OpenBSD__) && OpenBSD < 201510)) || \
57	defined(__APPLE__))
58#undef B0
59#undef B50
60#undef B75
61#undef B110
62#undef B134
63#undef B150
64#undef B200
65#undef B300
66#undef B600
67#undef B1200
68#undef B1800
69#undef B2400
70#undef B4800
71#undef B9600
72#undef B19200
73#undef EXTA
74#undef B38400
75#undef EXTB
76#undef B57600
77#undef B115200
78#undef B230400
79#undef B460800
80#undef B921600
81#define USE_OLD_TTY
82#include <sys/ttydev.h>
83#else
84#undef USE_OLD_TTY
85#endif /* USE_OLD_TTY */
86
87MODULE_ID("$Id: lib_baudrate.c,v 1.45 2020/09/05 21:15:32 tom Exp $")
88
89/*
90 *	int
91 *	baudrate()
92 *
93 *	Returns the current terminal's baud rate.
94 *
95 */
96
97struct speed {
98    int given_speed;		/* values for 'ospeed' */
99    int actual_speed;		/* the actual speed */
100};
101
102#if !defined(EXP_WIN32_DRIVER)
103#define DATA(number) { B##number, number }
104
105static struct speed const speeds[] =
106{
107    DATA(0),
108    DATA(50),
109    DATA(75),
110    DATA(110),
111    DATA(134),
112    DATA(150),
113    DATA(200),
114    DATA(300),
115    DATA(600),
116    DATA(1200),
117    DATA(1800),
118    DATA(2400),
119    DATA(4800),
120    DATA(9600),
121#ifdef B19200
122    DATA(19200),
123#elif defined(EXTA)
124    {EXTA, 19200},
125#endif
126#ifdef B28800
127    DATA(28800),
128#endif
129#ifdef B38400
130    DATA(38400),
131#elif defined(EXTB)
132    {EXTB, 38400},
133#endif
134#ifdef B57600
135    DATA(57600),
136#endif
137    /* ifdef to prevent overflow when OLD_TTY is not available */
138#if !(NCURSES_OSPEED_COMPAT && defined(__FreeBSD__) && (__FreeBSD_version > 700000))
139#ifdef B76800
140    DATA(76800),
141#endif
142#ifdef B115200
143    DATA(115200),
144#endif
145#ifdef B153600
146    DATA(153600),
147#endif
148#ifdef B230400
149    DATA(230400),
150#endif
151#ifdef B307200
152    DATA(307200),
153#endif
154#ifdef B460800
155    DATA(460800),
156#endif
157#ifdef B500000
158    DATA(500000),
159#endif
160#ifdef B576000
161    DATA(576000),
162#endif
163#ifdef B921600
164    DATA(921600),
165#endif
166#ifdef B1000000
167    DATA(1000000),
168#endif
169#ifdef B1152000
170    DATA(1152000),
171#endif
172#ifdef B1500000
173    DATA(1500000),
174#endif
175#ifdef B2000000
176    DATA(2000000),
177#endif
178#ifdef B2500000
179    DATA(2500000),
180#endif
181#ifdef B3000000
182    DATA(3000000),
183#endif
184#ifdef B3500000
185    DATA(3500000),
186#endif
187#ifdef B4000000
188    DATA(4000000),
189#endif
190#endif
191};
192#endif /* !EXP_WIN32_DRIVER */
193
194NCURSES_EXPORT(int)
195_nc_baudrate(int OSpeed)
196{
197#if defined(EXP_WIN32_DRIVER)
198    /* On Windows this is a noop */
199    (void) OSpeed;
200    return (OK);
201#else
202#if !USE_REENTRANT
203    static int last_OSpeed;
204    static int last_baudrate;
205#endif
206
207    int result = ERR;
208
209    if (OSpeed < 0)
210	OSpeed = (NCURSES_OSPEED) OSpeed;
211    if (OSpeed < 0)
212	OSpeed = (unsigned short) OSpeed;
213#if !USE_REENTRANT
214    if (OSpeed == last_OSpeed) {
215	result = last_baudrate;
216    }
217#endif
218    if (result == ERR) {
219	if (OSpeed >= 0) {
220	    unsigned i;
221
222	    for (i = 0; i < SIZEOF(speeds); i++) {
223		if (speeds[i].given_speed > OSpeed) {
224		    break;
225		}
226		if (speeds[i].given_speed == OSpeed) {
227		    result = speeds[i].actual_speed;
228		    break;
229		}
230	    }
231	}
232#if !USE_REENTRANT
233	if (OSpeed != last_OSpeed) {
234	    last_OSpeed = OSpeed;
235	    last_baudrate = result;
236	}
237#endif
238    }
239    return (result);
240#endif /* !EXP_WIN32_DRIVER */
241}
242
243NCURSES_EXPORT(int)
244_nc_ospeed(int BaudRate)
245{
246    int result = 1;
247#if defined(EXP_WIN32_DRIVER)
248    (void) BaudRate;
249#else
250    if (BaudRate >= 0) {
251	unsigned i;
252
253	for (i = 0; i < SIZEOF(speeds); i++) {
254	    if (speeds[i].actual_speed == BaudRate) {
255		result = speeds[i].given_speed;
256		break;
257	    }
258	}
259    }
260#endif
261    return (result);
262}
263
264NCURSES_EXPORT(int)
265NCURSES_SP_NAME(baudrate) (NCURSES_SP_DCL0)
266{
267    int result;
268
269    T((T_CALLED("baudrate(%p)"), (void *) SP_PARM));
270
271#if defined(EXP_WIN32_DRIVER)
272    result = OK;
273#else
274    /*
275     * In debugging, allow the environment symbol to override when we're
276     * redirecting to a file, so we can construct repeatable test-cases
277     * that take into account costs that depend on baudrate.
278     */
279#ifdef TRACE
280    if (IsValidTIScreen(SP_PARM)
281	&& !NC_ISATTY(fileno((SP_PARM && SP_PARM->_ofp) ? SP_PARM->_ofp : stdout))
282	&& getenv("BAUDRATE") != 0) {
283	int ret;
284	if ((ret = _nc_getenv_num("BAUDRATE")) <= 0)
285	    ret = 9600;
286	ospeed = (NCURSES_OSPEED) _nc_ospeed(ret);
287	returnCode(ret);
288    }
289#endif
290
291    if (IsValidTIScreen(SP_PARM)) {
292#ifdef USE_OLD_TTY
293	result = (int) cfgetospeed(&(TerminalOf(SP_PARM)->Nttyb));
294	ospeed = (NCURSES_OSPEED) _nc_ospeed(result);
295#else /* !USE_OLD_TTY */
296#ifdef TERMIOS
297	ospeed = (NCURSES_OSPEED) cfgetospeed(&(TerminalOf(SP_PARM)->Nttyb));
298#else
299	ospeed = (NCURSES_OSPEED) TerminalOf(SP_PARM)->Nttyb.sg_ospeed;
300#endif
301	result = _nc_baudrate(ospeed);
302#endif
303	TerminalOf(SP_PARM)->_baudrate = result;
304    } else {
305	result = ERR;
306    }
307#endif /* !EXP_WIN32_DRIVER */
308    returnCode(result);
309}
310
311#if NCURSES_SP_FUNCS
312NCURSES_EXPORT(int)
313baudrate(void)
314{
315    return NCURSES_SP_NAME(baudrate) (CURRENT_SCREEN);
316}
317#endif
318