xref: /illumos-gate/usr/src/cmd/bnu/setmode.c (revision bc1f688b4872ace323eaddbb1a6365d054e7bf56)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 1983 Regents of the University of California.
8  * All rights reserved. The Berkeley software License Agreement
9  * specifies the terms and conditions for redistribution.
10  */
11 
12 #pragma ident	"%Z%%M%	%I%	%E% SMI"
13 
14 /*
15  * Stolen from ucb/lpr/printjob.c
16  */
17 
18 #include <string.h>
19 #include "uucp.h"
20 
21 static struct termios termios_set;
22 static struct termios termios_clear;
23 
24 static int parse_modes(char *modes);
25 static void setty(int);
26 
27 int
28 setmode(modes, fd)
29 	char *modes;
30 	int fd;
31 {
32 	if (parse_modes(modes))
33 		setty(fd);
34 	return (0);
35 }
36 
37 struct mds {
38 	char	*string;
39 	unsigned long	set;
40 	unsigned long	reset;
41 };
42 						/* Control Modes */
43 static struct mds cmodes[] = {
44 	"-parity", CS8, PARENB|CSIZE,
45 	"-evenp", CS8, PARENB|CSIZE,
46 	"-oddp", CS8, PARENB|PARODD|CSIZE,
47 	"parity", PARENB|CS7, PARODD|CSIZE,
48 	"evenp", PARENB|CS7, PARODD|CSIZE,
49 	"oddp", PARENB|PARODD|CS7, CSIZE,
50 	"parenb", PARENB, 0,
51 	"-parenb", 0, PARENB,
52 	"parodd", PARODD, 0,
53 	"-parodd", 0, PARODD,
54 	"cs8", CS8, CSIZE,
55 	"cs7", CS7, CSIZE,
56 	"cs6", CS6, CSIZE,
57 	"cs5", CS5, CSIZE,
58 	"cstopb", CSTOPB, 0,
59 	"-cstopb", 0, CSTOPB,
60 	"stopb", CSTOPB, 0,
61 	"-stopb", 0, CSTOPB,
62 	"hupcl", HUPCL, 0,
63 	"hup", HUPCL, 0,
64 	"-hupcl", 0, HUPCL,
65 	"-hup", 0, HUPCL,
66 	"clocal", CLOCAL, 0,
67 	"-clocal", 0, CLOCAL,
68 	"nohang", CLOCAL, 0,
69 	"-nohang", 0, CLOCAL,
70 #if 0		/* this bit isn't supported */
71 	"loblk", LOBLK, 0,
72 	"-loblk", 0, LOBLK,
73 #endif
74 	"cread", CREAD, 0,
75 	"-cread", 0, CREAD,
76 #ifndef CRTSCTS
77 #define	CRTSCTS	0x80000000
78 #endif
79 	"crtscts", CRTSCTS, 0,
80 	"-crtscts", 0, CRTSCTS,
81 #ifndef CRTSXOFF
82 #define	CRTSXOFF 0x40000000
83 #endif
84 	"crtsxoff", CRTSXOFF, 0,
85 	"-crtsxoff", 0, CRTSXOFF,
86 	"litout", CS8, (CSIZE|PARENB),
87 	"-litout", (CS7|PARENB), CSIZE,
88 	"pass8", CS8, (CSIZE|PARENB),
89 	"-pass8", (CS7|PARENB), CSIZE,
90 	"raw", CS8, (CSIZE|PARENB),
91 	"-raw", (CS7|PARENB), CSIZE,
92 	"cooked", (CS7|PARENB), CSIZE,
93 	"sane", (CS7|PARENB|CREAD), (CSIZE|PARODD|CLOCAL),
94 	0
95 };
96 						/* Input Modes */
97 static struct mds imodes[] = {
98 	"ignbrk", IGNBRK, 0,
99 	"-ignbrk", 0, IGNBRK,
100 	"brkint", BRKINT, 0,
101 	"-brkint", 0, BRKINT,
102 	"ignpar", IGNPAR, 0,
103 	"-ignpar", 0, IGNPAR,
104 	"parmrk", PARMRK, 0,
105 	"-parmrk", 0, PARMRK,
106 	"inpck", INPCK, 0,
107 	"-inpck", 0, INPCK,
108 	"istrip", ISTRIP, 0,
109 	"-istrip", 0, ISTRIP,
110 	"inlcr", INLCR, 0,
111 	"-inlcr", 0, INLCR,
112 	"igncr", IGNCR, 0,
113 	"-igncr", 0, IGNCR,
114 	"icrnl", ICRNL, 0,
115 	"-icrnl", 0, ICRNL,
116 	"-nl", ICRNL, (INLCR|IGNCR),
117 	"nl", 0, ICRNL,
118 	"iuclc", IUCLC, 0,
119 	"-iuclc", 0, IUCLC,
120 	"lcase", IUCLC, 0,
121 	"-lcase", 0, IUCLC,
122 	"LCASE", IUCLC, 0,
123 	"-LCASE", 0, IUCLC,
124 	"ixon", IXON, 0,
125 	"-ixon", 0, IXON,
126 	"ixany", IXANY, 0,
127 	"-ixany", 0, IXANY,
128 	"decctlq", 0, IXANY,
129 	"-decctlq", IXANY, 0,
130 	"ixoff", IXOFF, 0,
131 	"-ixoff", 0, IXOFF,
132 	"tandem", IXOFF, 0,
133 	"-tandem", 0, IXOFF,
134 	"imaxbel", IMAXBEL, 0,
135 	"-imaxbel", 0, IMAXBEL,
136 	"pass8", 0, ISTRIP,
137 	"-pass8", ISTRIP, 0,
138 	"raw", 0, (unsigned long)-1,
139 	"-raw", (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON|IMAXBEL), 0,
140 	"cooked", (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON), 0,
141 	"sane", (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON|IMAXBEL),
142 		(IGNBRK|PARMRK|INPCK|INLCR|IGNCR|IUCLC|IXOFF),
143 	0
144 };
145 						/* Local Modes */
146 static struct mds lmodes[] = {
147 	"isig", ISIG, 0,
148 	"-isig", 0, ISIG,
149 	"noisig", 0, ISIG,
150 	"-noisig", ISIG, 0,
151 	"iexten", IEXTEN, 0,
152 	"-iexten", 0, IEXTEN,
153 	"icanon", ICANON, 0,
154 	"-icanon", 0, ICANON,
155 	"cbreak", 0, ICANON,
156 	"-cbreak", ICANON, 0,
157 	"xcase", XCASE, 0,
158 	"-xcase", 0, XCASE,
159 	"lcase", XCASE, 0,
160 	"-lcase", 0, XCASE,
161 	"LCASE", XCASE, 0,
162 	"-LCASE", 0, XCASE,
163 	"echo", ECHO, 0,
164 	"-echo", 0, ECHO,
165 	"echoe", ECHOE, 0,
166 	"-echoe", 0, ECHOE,
167 	"crterase", ECHOE, 0,
168 	"-crterase", 0, ECHOE,
169 	"echok", ECHOK, 0,
170 	"-echok", 0, ECHOK,
171 	"lfkc", ECHOK, 0,
172 	"-lfkc", 0, ECHOK,
173 	"echonl", ECHONL, 0,
174 	"-echonl", 0, ECHONL,
175 	"noflsh", NOFLSH, 0,
176 	"-noflsh", 0, NOFLSH,
177 	"tostop", TOSTOP, 0,
178 	"-tostop", 0, TOSTOP,
179 	"echoctl", ECHOCTL, 0,
180 	"-echoctl", 0, ECHOCTL,
181 	"ctlecho", ECHOCTL, 0,
182 	"-ctlecho", 0, ECHOCTL,
183 	"echoprt", ECHOPRT, 0,
184 	"-echoprt", 0, ECHOPRT,
185 	"prterase", ECHOPRT, 0,
186 	"-prterase", 0, ECHOPRT,
187 	"echoke", ECHOKE, 0,
188 	"-echoke", 0, ECHOKE,
189 	"crtkill", ECHOKE, 0,
190 	"-crtkill", 0, ECHOKE,
191 #if 0		/* this bit isn't supported yet */
192 	"defecho", DEFECHO, 0,
193 	"-defecho", 0, DEFECHO,
194 #endif
195 	"raw", 0, (ISIG|ICANON|XCASE|IEXTEN),
196 	"-raw", (ISIG|ICANON|IEXTEN), 0,
197 	"cooked", (ISIG|ICANON), 0,
198 	"sane", (ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE),
199 		(XCASE|ECHOPRT|ECHONL|NOFLSH),
200 	0,
201 };
202 						/* Output Modes */
203 static struct mds omodes[] = {
204 	"opost", OPOST, 0,
205 	"-opost", 0, OPOST,
206 	"nopost", 0, OPOST,
207 	"-nopost", OPOST, 0,
208 	"olcuc", OLCUC, 0,
209 	"-olcuc", 0, OLCUC,
210 	"lcase", OLCUC, 0,
211 	"-lcase", 0, OLCUC,
212 	"LCASE", OLCUC, 0,
213 	"-LCASE", 0, OLCUC,
214 	"onlcr", ONLCR, 0,
215 	"-onlcr", 0, ONLCR,
216 	"-nl", ONLCR, (OCRNL|ONLRET),
217 	"nl", 0, ONLCR,
218 	"ocrnl", OCRNL, 0,
219 	"-ocrnl", 0, OCRNL,
220 	"onocr", ONOCR, 0,
221 	"-onocr", 0, ONOCR,
222 	"onlret", ONLRET, 0,
223 	"-onlret", 0, ONLRET,
224 	"fill", OFILL, OFDEL,
225 	"-fill", 0, OFILL|OFDEL,
226 	"nul-fill", OFILL, OFDEL,
227 	"del-fill", OFILL|OFDEL, 0,
228 	"ofill", OFILL, 0,
229 	"-ofill", 0, OFILL,
230 	"ofdel", OFDEL, 0,
231 	"-ofdel", 0, OFDEL,
232 	"cr0", CR0, CRDLY,
233 	"cr1", CR1, CRDLY,
234 	"cr2", CR2, CRDLY,
235 	"cr3", CR3, CRDLY,
236 	"tab0", TAB0, TABDLY,
237 	"tabs", TAB0, TABDLY,
238 	"tab1", TAB1, TABDLY,
239 	"tab2", TAB2, TABDLY,
240 	"-tabs", XTABS, TABDLY,
241 	"tab3", XTABS, TABDLY,
242 	"nl0", NL0, NLDLY,
243 	"nl1", NL1, NLDLY,
244 	"ff0", FF0, FFDLY,
245 	"ff1", FF1, FFDLY,
246 	"vt0", VT0, VTDLY,
247 	"vt1", VT1, VTDLY,
248 	"bs0", BS0, BSDLY,
249 	"bs1", BS1, BSDLY,
250 #if 0		/* these bits aren't supported yet */
251 	"pageout", PAGEOUT, 0,
252 	"-pageout", 0, PAGEOUT,
253 	"wrap", WRAP, 0,
254 	"-wrap", 0, WRAP,
255 #endif
256 	"litout", 0, OPOST,
257 	"-litout", OPOST, 0,
258 	"raw", 0, OPOST,
259 	"-raw", OPOST, 0,
260 	"cooked", OPOST, 0,
261 	"33", CR1, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
262 	"tty33", CR1, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
263 	"tn", CR1, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
264 	"tn300", CR1, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
265 	"ti", CR2, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
266 	"ti700", CR2, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
267 	"05", NL1, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
268 	"vt05", NL1, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
269 	"tek", FF1, (CRDLY|TABDLY|NLDLY|FFDLY|VTDLY|BSDLY),
270 	"37", (FF1|VT1|CR2|TAB1|NL1), (NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY),
271 	"tty37", (FF1|VT1|CR2|TAB1|NL1), (NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY),
272 	"sane", (OPOST|ONLCR), (OLCUC|OCRNL|ONOCR|ONLRET|OFILL|OFDEL|
273 			NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY),
274 	0,
275 };
276 
277 /*
278  * Parse a set of modes.
279  */
280 static int
281 parse_modes(modes)
282 	char *modes;
283 {
284 	char *curtoken;
285 	int match;
286 	int i;
287 
288 	termios_clear.c_iflag = 0;
289 	termios_clear.c_oflag = 0;
290 	termios_clear.c_cflag = 0;
291 	termios_clear.c_lflag = 0;
292 	termios_set.c_iflag = 0;
293 	termios_set.c_oflag = 0;
294 	termios_set.c_cflag = 0;
295 	termios_set.c_lflag = 0;
296 
297 	curtoken = strtok(modes, ",");
298 	while (curtoken != NULL) {
299 		match = 0;
300 		for (i = 0; imodes[i].string != NULL; i++) {
301 			if (strcmp(curtoken, imodes[i].string) == 0) {
302 				match++;
303 				termios_clear.c_iflag |= imodes[i].reset;
304 				termios_set.c_iflag |= imodes[i].set;
305 			}
306 		}
307 		for (i = 0; omodes[i].string != NULL; i++) {
308 			if (strcmp(curtoken, omodes[i].string) == 0) {
309 				match++;
310 				termios_clear.c_oflag |= omodes[i].reset;
311 				termios_set.c_oflag |= omodes[i].set;
312 			}
313 		}
314 		for (i = 0; cmodes[i].string != NULL; i++) {
315 			if (strcmp(curtoken, cmodes[i].string) == 0) {
316 				match++;
317 				termios_clear.c_cflag |= cmodes[i].reset;
318 				termios_set.c_cflag |= cmodes[i].set;
319 			}
320 		}
321 		for (i = 0; lmodes[i].string != NULL; i++) {
322 			if (strcmp(curtoken, lmodes[i].string) == 0) {
323 				match++;
324 				termios_clear.c_lflag |= lmodes[i].reset;
325 				termios_set.c_lflag |= lmodes[i].set;
326 			}
327 		}
328 		if (!match) {
329 			CDEBUG(5, "unknown mode %s in STTY= string", curtoken);
330 			return (0);
331 		}
332 		curtoken = strtok((char *)NULL, ",");
333 	}
334 	return (1);
335 }
336 
337 /*
338  * setup tty lines.
339  */
340 static void
341 setty(int fd)
342 {
343 	struct termios termios;
344 
345 	if ((*Ioctl)(fd, TCGETS, &termios) < 0) {
346 		CDEBUG(5, "ioctl(TCGETS): %d", errno);
347 		return;
348 	}
349 
350 	termios.c_iflag &= ~termios_clear.c_iflag;
351 	termios.c_iflag |= termios_set.c_iflag;
352 	termios.c_oflag &= ~termios_clear.c_oflag;
353 	termios.c_oflag |= termios_set.c_oflag;
354 	termios.c_cflag &= ~termios_clear.c_cflag;
355 	termios.c_cflag |= termios_set.c_cflag;
356 	termios.c_lflag &= ~termios_clear.c_lflag;
357 	termios.c_lflag |= termios_set.c_lflag;
358 
359 	if ((*Ioctl)(fd, TCSETSF, &termios) < 0) {
360 		CDEBUG(5, "ioctl(TCSETSF): %d", errno);
361 		return;
362 	}
363 }
364