GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: libexec/getty/subr.c Lines: 0 181 0.0 %
Date: 2017-11-07 Branches: 0 157 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: subr.c,v 1.27 2017/05/27 07:37:36 tedu Exp $	*/
2
3
/*
4
 * Copyright (c) 1983, 1993
5
 *	The Regents of the University of California.  All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 * 3. Neither the name of the University nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
/*
33
 * Melbourne getty.
34
 */
35
#include <sys/ioctl.h>
36
#include <stdlib.h>
37
#include <unistd.h>
38
#include <string.h>
39
#include <poll.h>
40
#include <termios.h>
41
42
#include "gettytab.h"
43
#include "pathnames.h"
44
#include "extern.h"
45
46
extern	struct termios tmode, omode;
47
48
/*
49
 * Get a table entry.
50
 */
51
void
52
gettable(char *name, char *buf)
53
{
54
	struct gettystrs *sp;
55
	struct gettynums *np;
56
	struct gettyflags *fp;
57
	long n;
58
	char *dba[2];
59
	dba[0] = _PATH_GETTYTAB;
60
	dba[1] = NULL;
61
62
	if (cgetent(&buf, dba, name) != 0)
63
		return;
64
65
	for (sp = gettystrs; sp->field; sp++)
66
		cgetstr(buf, sp->field, &sp->value);
67
	for (np = gettynums; np->field; np++) {
68
		if (cgetnum(buf, np->field, &n) == -1)
69
			np->set = 0;
70
		else {
71
			np->set = 1;
72
			np->value = n;
73
		}
74
	}
75
	for (fp = gettyflags; fp->field; fp++) {
76
		if (cgetcap(buf, fp->field, ':') == NULL)
77
			fp->set = 0;
78
		else {
79
			fp->set = 1;
80
			fp->value = 1 ^ fp->invrt;
81
		}
82
	}
83
#ifdef DEBUG
84
	printf("name=\"%s\", buf=\"%s\"\n", name, buf);
85
	for (sp = gettystrs; sp->field; sp++)
86
		printf("cgetstr: %s=%s\n", sp->field, sp->value);
87
	for (np = gettynums; np->field; np++)
88
		printf("cgetnum: %s=%d\n", np->field, np->value);
89
	for (fp = gettyflags; fp->field; fp++)
90
		printf("cgetflags: %s='%c' set='%c'\n", fp->field,
91
		    fp->value + '0', fp->set + '0');
92
	exit(1);
93
#endif /* DEBUG */
94
}
95
96
void
97
gendefaults(void)
98
{
99
	struct gettystrs *sp;
100
	struct gettynums *np;
101
	struct gettyflags *fp;
102
103
	for (sp = gettystrs; sp->field; sp++)
104
		if (sp->value)
105
			sp->defalt = sp->value;
106
	for (np = gettynums; np->field; np++)
107
		if (np->set)
108
			np->defalt = np->value;
109
	for (fp = gettyflags; fp->field; fp++)
110
		if (fp->set)
111
			fp->defalt = fp->value;
112
		else
113
			fp->defalt = fp->invrt;
114
}
115
116
void
117
setdefaults(void)
118
{
119
	struct gettystrs *sp;
120
	struct gettynums *np;
121
	struct gettyflags *fp;
122
123
	for (sp = gettystrs; sp->field; sp++)
124
		if (!sp->value)
125
			sp->value = sp->defalt;
126
	for (np = gettynums; np->field; np++)
127
		if (!np->set)
128
			np->value = np->defalt;
129
	for (fp = gettyflags; fp->field; fp++)
130
		if (!fp->set)
131
			fp->value = fp->defalt;
132
}
133
134
static char **
135
charnames[] = {
136
	&ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
137
	&SU, &DS, &RP, &FL, &WE, &LN, 0
138
};
139
140
static char *
141
charvars[] = {
142
	&tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
143
	&tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
144
	&tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
145
	&tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
146
	&tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
147
};
148
149
void
150
setchars(void)
151
{
152
	int i;
153
	char *p;
154
155
	for (i = 0; charnames[i]; i++) {
156
		p = *charnames[i];
157
		if (p && *p)
158
			*charvars[i] = *p;
159
		else
160
			*charvars[i] = _POSIX_VDISABLE;
161
	}
162
}
163
164
/* Macros to clear/set/test flags. */
165
#define	SET(t, f)	(t) |= (f)
166
#define	CLR(t, f)	(t) &= ~(f)
167
#define	ISSET(t, f)	((t) & (f))
168
169
void
170
setflags(int n)
171
{
172
	tcflag_t iflag, oflag, cflag, lflag;
173
174
	switch (n) {
175
	case 0:
176
		if (C0set && I0set && L0set && O0set) {
177
			tmode.c_cflag = C0;
178
			tmode.c_iflag = I0;
179
			tmode.c_lflag = L0;
180
			tmode.c_oflag = O0;
181
			return;
182
		}
183
		break;
184
	case 1:
185
		if (C1set && I1set && L1set && O1set) {
186
			tmode.c_cflag = C1;
187
			tmode.c_iflag = I1;
188
			tmode.c_lflag = L1;
189
			tmode.c_oflag = O1;
190
			return;
191
		}
192
		break;
193
	default:
194
		if (C2set && I2set && L2set && O2set) {
195
			tmode.c_cflag = C2;
196
			tmode.c_iflag = I2;
197
			tmode.c_lflag = L2;
198
			tmode.c_oflag = O2;
199
			return;
200
		}
201
		break;
202
	}
203
204
	iflag = omode.c_iflag;
205
	oflag = omode.c_oflag;
206
	cflag = omode.c_cflag;
207
	lflag = omode.c_lflag;
208
209
	if (NP) {
210
		CLR(cflag, CSIZE|PARENB);
211
		SET(cflag, CS8);
212
		CLR(iflag, ISTRIP|INPCK|IGNPAR);
213
	} else if (AP || EP || OP) {
214
		CLR(cflag, CSIZE);
215
		SET(cflag, CS7|PARENB);
216
		SET(iflag, ISTRIP);
217
		if (OP && !EP) {
218
			SET(iflag, INPCK|IGNPAR);
219
			SET(cflag, PARODD);
220
			if (AP)
221
				CLR(iflag, INPCK);
222
		} else if (EP && !OP) {
223
			SET(iflag, INPCK|IGNPAR);
224
			CLR(cflag, PARODD);
225
			if (AP)
226
				CLR(iflag, INPCK);
227
		} else if (AP || (EP && OP)) {
228
			CLR(iflag, INPCK|IGNPAR);
229
			CLR(cflag, PARODD);
230
		}
231
	} /* else, leave as is */
232
233
	if (UC) {
234
		SET(iflag, IUCLC);
235
		SET(oflag, OLCUC);
236
		SET(lflag, XCASE);
237
	}
238
239
	if (HC)
240
		SET(cflag, HUPCL);
241
	else
242
		CLR(cflag, HUPCL);
243
244
	if (MB)
245
		SET(cflag, MDMBUF);
246
	else
247
		CLR(cflag, MDMBUF);
248
249
	if (NL) {
250
		SET(iflag, ICRNL);
251
		SET(oflag, ONLCR|OPOST);
252
	} else {
253
		CLR(iflag, ICRNL);
254
		CLR(oflag, ONLCR);
255
	}
256
257
	if (!HT)
258
		SET(oflag, OXTABS|OPOST);
259
	else
260
		CLR(oflag, OXTABS);
261
262
263
	if (n == 1) {		/* read mode flags */
264
		if (RW) {
265
			iflag = 0;
266
			CLR(oflag, OPOST);
267
			CLR(cflag, CSIZE|PARENB);
268
			SET(cflag, CS8);
269
			lflag = 0;
270
		} else {
271
			CLR(lflag, ICANON);
272
		}
273
		goto out;
274
	}
275
276
	if (n == 0)
277
		goto out;
278
279
#if 0
280
	if (CB)
281
		SET(f, CRTBS);
282
#endif
283
284
	if (CE)
285
		SET(lflag, ECHOE);
286
	else
287
		CLR(lflag, ECHOE);
288
289
	if (CK)
290
		SET(lflag, ECHOKE);
291
	else
292
		CLR(lflag, ECHOKE);
293
294
	if (PE)
295
		SET(lflag, ECHOPRT);
296
	else
297
		CLR(lflag, ECHOPRT);
298
299
	if (EC)
300
		SET(lflag, ECHO);
301
	else
302
		CLR(lflag, ECHO);
303
304
	if (XC)
305
		SET(lflag, ECHOCTL);
306
	else
307
		CLR(lflag, ECHOCTL);
308
309
	if (DX)
310
		SET(lflag, IXANY);
311
	else
312
		CLR(lflag, IXANY);
313
314
out:
315
	tmode.c_iflag = iflag;
316
	tmode.c_oflag = oflag;
317
	tmode.c_cflag = cflag;
318
	tmode.c_lflag = lflag;
319
}
320
321
322
void
323
makeenv(char *env[])
324
{
325
	static char termbuf[128] = "TERM=";
326
	char *p, *q;
327
	char **ep;
328
329
	ep = env;
330
	if (TT && *TT) {
331
		strlcat(termbuf, TT, sizeof(termbuf));
332
		*ep++ = termbuf;
333
	}
334
	if ((p = EV)) {
335
		q = p;
336
		while ((q = strchr(q, ','))) {
337
			*q++ = '\0';
338
			*ep++ = p;
339
			p = q;
340
		}
341
		if (*p)
342
			*ep++ = p;
343
	}
344
	*ep = NULL;
345
}
346
347
/*
348
 * This speed select mechanism is written for the Develcon DATASWITCH.
349
 * The Develcon sends a string of the form "B{speed}\n" at a predefined
350
 * baud rate. This string indicates the user's actual speed.
351
 * The routine below returns the terminal type mapped from derived speed.
352
 */
353
struct	portselect {
354
	char	*ps_baud;
355
	char	*ps_type;
356
} portspeeds[] = {
357
	{ "B110",	"std.110" },
358
	{ "B134",	"std.134" },
359
	{ "B150",	"std.150" },
360
	{ "B300",	"std.300" },
361
	{ "B600",	"std.600" },
362
	{ "B1200",	"std.1200" },
363
	{ "B2400",	"std.2400" },
364
	{ "B4800",	"std.4800" },
365
	{ "B9600",	"std.9600" },
366
	{ "B19200",	"std.19200" },
367
	{ 0 }
368
};
369
370
char *
371
portselector(void)
372
{
373
	char c, baud[20], *type = "default";
374
	struct portselect *ps;
375
	int len;
376
377
	alarm(5*60);
378
	for (len = 0; len < sizeof (baud) - 1; len++) {
379
		if (read(STDIN_FILENO, &c, 1) <= 0)
380
			break;
381
		c &= 0177;
382
		if (c == '\n' || c == '\r')
383
			break;
384
		if (c == 'B')
385
			len = 0;	/* in case of leading garbage */
386
		baud[len] = c;
387
	}
388
	baud[len] = '\0';
389
	for (ps = portspeeds; ps->ps_baud; ps++)
390
		if (strcmp(ps->ps_baud, baud) == 0) {
391
			type = ps->ps_type;
392
			break;
393
		}
394
	sleep(2);	/* wait for connection to complete */
395
	return (type);
396
}
397
398
/*
399
 * This auto-baud speed select mechanism is written for the Micom 600
400
 * portselector. Selection is done by looking at how the character '\r'
401
 * is garbled at the different speeds.
402
 */
403
#include <sys/time.h>
404
405
char *
406
autobaud(void)
407
{
408
	struct pollfd pfd[1];
409
	struct timespec ts;
410
	char c, *type = "9600-baud";
411
412
	(void)tcflush(0, TCIOFLUSH);
413
	pfd[0].fd = 0;
414
	pfd[0].events = POLLIN;
415
	if (poll(pfd, 1, 5 * 1000) <= 0)
416
		return (type);
417
	if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
418
		return (type);
419
420
	ts.tv_sec = 0;
421
	ts.tv_nsec = 20 * 1000;
422
	nanosleep(&ts, NULL);
423
	(void)tcflush(0, TCIOFLUSH);
424
	switch (c & 0377) {
425
426
	case 0200:		/* 300-baud */
427
		type = "300-baud";
428
		break;
429
430
	case 0346:		/* 1200-baud */
431
		type = "1200-baud";
432
		break;
433
434
	case  015:		/* 2400-baud */
435
	case 0215:
436
		type = "2400-baud";
437
		break;
438
439
	default:		/* 4800-baud */
440
		type = "4800-baud";
441
		break;
442
443
	case 0377:		/* 9600-baud */
444
		type = "9600-baud";
445
		break;
446
	}
447
	return (type);
448
}