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