1 /* $MirOS: src/usr.sbin/wsconfig/wsconfig.c,v 1.16 2007/05/10 13:02:21 tg Exp $ */
2
3 /*-
4 * Copyright (c) 2006, 2007
5 * Thorsten Glaser <tg@mirbsd.de>
6 *
7 * Provided that these terms and disclaimer and all copyright notices
8 * are retained or reproduced in an accompanying document, permission
9 * is granted to deal in this work without restriction, including un-
10 * limited rights to use, publicly perform, distribute, sell, modify,
11 * merge, give away, or sublicence.
12 *
13 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
14 * the utmost extent permitted by applicable law, neither express nor
15 * implied; without malicious intent or gross negligence. In no event
16 * may a licensor, author or contributor be held liable for indirect,
17 * direct, other damage, loss, or other issues arising in any way out
18 * of dealing in the work, even if advised of the possibility of such
19 * damage or existence of a defect, except proven that it results out
20 * of said person's immediate fault when using the work as intended.
21 */
22
23 #include <sys/param.h>
24 #include <sys/ioctl.h>
25 #include <dev/wscons/wsconsio.h>
26 #include <dev/wscons/wsdisplay_usl_io.h>
27 #include <dev/wscons/wsdisplayvar.h>
28 #include <ctype.h>
29 #include <err.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <termios.h>
36 #include <unistd.h>
37
38 __RCSID("$MirOS: src/usr.sbin/wsconfig/wsconfig.c,v 1.16 2007/05/10 13:02:21 tg Exp $");
39 __RCSID("$miros: ports/sysutils/chkuterm/dist/chkuterm.c,v 1.11 2007/05/10 13:02:22 tg Exp $");
40 __RCSID("$miros: ports/misc/screen/patches/patch-screen_c,v 1.12 2007/05/10 13:02:23 tg Exp $");
41
42 #define DEFDEV "/dev/ttyCcfg"
43
44 /* query string sent to the terminal for LC_CTYPE detection */
45 /* XXX is U+20AC U+002E ok or some other char better? Think EUC, SJIS, etc. */
46 const char ctype_qstr[] = "\030\032\r\xE2\x82\xAC.\033[6n";
47
48 #ifndef SMALL
49 __dead void usage(void);
50 #endif
51
52 /*
53 * common options:
54 * -f <device> select device on which to operate
55 * -q be more quiet
56 * -? help
57 *
58 *
59 * operation modes:
60 *
61 * === default device: /dev/ttyCcfg ===
62 * -I <number> dump info about font in slot #number
63 * -S print out active VT number
64 * -s <number> activate VT #number
65 *
66 * === default device: ttyname(stdin) ===
67 * -o <name> select font #name
68 * -U return true and print (unless -q) if VT is UTF-8
69 */
70
71 int
72 #ifdef SMALL
main(void)73 main(void) /* like -U -q */
74 #else
75 main(int argc, char **argv)
76 #endif
77 {
78 const char *wsdev, *est;
79 char ch;
80 int wsfd, c, rv = 0;
81 int action = 0, nr = 0;
82 struct termios tio, otio;
83 fd_set fds;
84 struct timeval tv;
85 FILE *wsf;
86 #ifndef SMALL
87 struct wsdisplay_font f;
88 int q = 0;
89
90 wsdev = DEFDEV;
91 while ((c = getopt(argc, argv, "f:I:o:qSs:U")) != -1)
92 switch (c) {
93 case 'f':
94 wsdev = optarg;
95 break;
96 case 'I':
97 if (action)
98 usage();
99 else
100 action = 5;
101 nr = strtonum(optarg, 0, WSDISPLAY_MAXFONT - 1, &est);
102 if (est)
103 errx(1, "slot number %s is %s", optarg, est);
104 f.index = nr;
105 break;
106 case 'o':
107 if (action)
108 usage();
109 else
110 action = 4;
111 strlcpy(f.name, optarg, WSFONT_NAME_SIZE);
112 break;
113 case 'q':
114 q = 1;
115 break;
116 case 'S':
117 if (action)
118 usage();
119 else
120 action = 2;
121 break;
122 case 's':
123 if (action)
124 usage();
125 else
126 action = 1;
127 nr = strtonum(optarg, 1, 255, &est);
128 if (est)
129 errx(1, "console number %s is %s", optarg, est);
130 break;
131 case 'U':
132 if (action)
133 usage();
134 else
135 #endif
136 action = 6;
137 #ifndef SMALL
138 break;
139 default:
140 usage();
141 }
142 argc -= optind;
143 argv += optind;
144
145 if (!action)
146 usage();
147
148 if (wsdev == DEFDEV && (action == 4 || action == 6))
149 #endif
150 if ((wsdev = ttyname(STDIN_FILENO)) == NULL)
151 wsdev = "/dev/tty";
152
153 /* apparently O_RDONLY wouldn't matter but we stay safe */
154 if ((est = ttyname(STDIN_FILENO)) != NULL && !strcmp(wsdev, est))
155 wsfd = STDIN_FILENO;
156 else if ((est = ttyname(STDOUT_FILENO)) != NULL && !strcmp(wsdev, est))
157 wsfd = STDOUT_FILENO;
158 else
159 if ((wsfd = open(wsdev, O_RDWR, 0)) < 0)
160 err(2, "open %s", wsdev);
161 wsf = fdopen(wsfd, "rb+");
162
163 #ifndef SMALL
164 switch (action) {
165 case 1:
166 if (argc)
167 usage();
168 if (ioctl(wsfd, VT_ACTIVATE, nr) == -1)
169 err(3, "ioctl VT_ACTIVATE %d", nr);
170 break;
171 case 2:
172 if (argc)
173 usage();
174 if (ioctl(wsfd, VT_GETACTIVE, &nr) == -1)
175 err(3, "ioctl VT_GETACTIVE");
176 printf("%d\n", nr);
177 break;
178 case 4:
179 if (ioctl(wsfd, WSDISPLAYIO_USEFONT, &f) == -1)
180 err(3, "ioctl WSDISPLAYIO_USEFONT");
181 if (!q)
182 printf("selected font \"%s\"\n", f.name);
183 break;
184 case 5:
185 if (ioctl(wsfd, WSDISPLAYIO_LSFONT, &f) == -1)
186 err(3, "ioctl WSDISPLAYIO_LSFONT");
187 if (q)
188 printf("%s\n", f.name);
189 else {
190 printf("%32s%s\n", "Name:", f.name);
191 printf("%32s%d\n", "Index:", f.index);
192 printf("%32s%d\n", "First Character:", f.firstchar);
193 printf("%32s%d\n", "Number of Characters:", f.numchars);
194 printf("%32s%d\n", "Last Character:",
195 f.firstchar + f.numchars);
196 if ((unsigned)f.encoding < 5)
197 printf("%32s%s\n", "Encoding:",
198 (f.encoding == 0) ? "ISO (latin1)" :
199 (f.encoding == 1) ? "IBM (437)" :
200 (f.encoding == 2) ? "PCVT (special)" :
201 (f.encoding == 3) ? "ISO7 (greek)" :
202 "SONY");
203 else
204 printf("%32sUNKNOWN (%d)\n",
205 "Encoding:", f.encoding);
206 printf("%32s%u\n", "Font Width:", f.fontwidth);
207 printf("%32s%u\n", "Font Height:", f.fontheight);
208 printf("%32s%u\n", "Font Stride:", f.stride);
209 if ((unsigned)f.bitorder < 3)
210 printf("%32s%s\n", "Bit Order:",
211 (f.bitorder == 0) ? "KNOWN (host)" :
212 (f.bitorder == 1) ? "L2R" : "R2L");
213 else
214 printf("%32sUNKNOWN (%d)\n",
215 "Bit Order:", f.bitorder);
216 if ((unsigned)f.byteorder < 3)
217 printf("%32s%s\n", "Byte Order:",
218 (f.byteorder == 0) ? "KNOWN (host)" :
219 (f.byteorder == 1) ? "L2R" : "R2L");
220 else
221 printf("%32sUNKNOWN (%d)\n",
222 "Byte Order:", f.byteorder);
223 }
224 break;
225 case 6:
226 #endif
227 if (tcgetattr(wsfd, &otio))
228 err(3, "tcgetattr");
229 tio = otio;
230 cfmakeraw(&tio);
231 if (tcflush(wsfd, TCIOFLUSH))
232 warn("tcflush");
233 rv = /* error */ 3;
234 if (tcsetattr(wsfd, TCSANOW, &tio)) {
235 warn("tcsetattr\r");
236 goto tios_err;
237 }
238 tv.tv_sec = 0;
239 tv.tv_usec = 75;
240 select(0, NULL, NULL, NULL, &tv); /* sleep 75 msec */
241 if ((size_t)write(wsfd, ctype_qstr, strlen(ctype_qstr)) !=
242 strlen(ctype_qstr)) {
243 warn("write\r");
244 goto noin;
245 }
246 select(0, NULL, NULL, NULL, &tv); /* sleep 75 msec */
247 FD_ZERO(&fds);
248 FD_SET(wsfd, &fds);
249 tv.tv_sec = 2;
250 tv.tv_usec = 0;
251 if (select(wsfd + 1, &fds, NULL, NULL, &tv) <= 0)
252 goto noin;
253 nr = read(wsfd, &ch, 1);
254 rv = /* unknown */ 1;
255 if (wsf != NULL && nr == 1 && ch == 033) {
256 unsigned zeile, spalte;
257
258 if (fscanf(wsf, "[%u;%u", &zeile, &spalte) == 2)
259 switch (spalte) {
260 case 1: /* EUC-JP, EUC-KR kterm */
261 case 5: /* Shift-JIS kterm */
262 break;
263 case 3: /* UTF-8 xterm, screen */
264 rv = 0;
265 break;
266 case 4: /* ISO-8859-1 xterm, screen */
267 rv = 2;
268 break;
269 default:
270 rv = 0x1000 | spalte;
271 break;
272 }
273 }
274 noin:
275 write(wsfd, "\r \r", 8);
276 tios_err:
277 if (tcflush(wsfd, TCIOFLUSH))
278 warn("tcflush");
279 if (tcsetattr(wsfd, TCSANOW, &otio))
280 err(3, "tcsetattr");
281 #ifndef SMALL
282 if (rv & 0x1000) {
283 /* unknown charset */
284 if (!q)
285 printf("# unknown column %d\n", rv & 0xFFF);
286 rv = 1;
287 }
288 if (!q)
289 printf("LC_CTYPE=%s; export LC_CTYPE\n",
290 rv == 0 ? "en_US.UTF-8" : "C");
291 if (!q && rv > 2)
292 puts("# warning: problems occured!\n");
293 break;
294 default:
295 usage();
296 }
297 #endif
298
299 if (wsf == NULL)
300 close(wsfd);
301 else
302 fclose(wsf);
303 return (rv);
304 }
305
306 #ifndef SMALL
307 void
usage(void)308 usage(void)
309 {
310 extern const char *__progname;
311
312 fprintf(stderr, "Usage:\t%s -U\n"
313 "\t%s [-f ctldev] -s screen\n"
314 "\t%s [-q] [-f wsdev] { -I slot | -o name }\n",
315 __progname, __progname, __progname);
316 exit(1);
317 }
318 #endif
319