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
setmode(modes,fd)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
parse_modes(modes)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
setty(int fd)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