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