resize.c revision 1.1 1 1.1 reinoud /* $NetBSD: resize.c,v 1.1 2020/12/27 21:13:18 reinoud Exp $ */
2 1.1 reinoud /* $XTermId: resize.c,v 1.139 2017/05/31 08:58:56 tom Exp $ */
3 1.1 reinoud
4 1.1 reinoud /*
5 1.1 reinoud * Copyright 2003-2015,2017 by Thomas E. Dickey
6 1.1 reinoud *
7 1.1 reinoud * All Rights Reserved
8 1.1 reinoud *
9 1.1 reinoud * Permission is hereby granted, free of charge, to any person obtaining a
10 1.1 reinoud * copy of this software and associated documentation files (the
11 1.1 reinoud * "Software"), to deal in the Software without restriction, including
12 1.1 reinoud * without limitation the rights to use, copy, modify, merge, publish,
13 1.1 reinoud * distribute, sublicense, and/or sell copies of the Software, and to
14 1.1 reinoud * permit persons to whom the Software is furnished to do so, subject to
15 1.1 reinoud * the following conditions:
16 1.1 reinoud *
17 1.1 reinoud * The above copyright notice and this permission notice shall be included
18 1.1 reinoud * in all copies or substantial portions of the Software.
19 1.1 reinoud *
20 1.1 reinoud * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 1.1 reinoud * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 1.1 reinoud * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 1.1 reinoud * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
24 1.1 reinoud * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 1.1 reinoud * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 1.1 reinoud * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 1.1 reinoud *
28 1.1 reinoud * Except as contained in this notice, the name(s) of the above copyright
29 1.1 reinoud * holders shall not be used in advertising or otherwise to promote the
30 1.1 reinoud * sale, use or other dealings in this Software without prior written
31 1.1 reinoud * authorization.
32 1.1 reinoud *
33 1.1 reinoud *
34 1.1 reinoud * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
35 1.1 reinoud *
36 1.1 reinoud * All Rights Reserved
37 1.1 reinoud *
38 1.1 reinoud * Permission to use, copy, modify, and distribute this software and its
39 1.1 reinoud * documentation for any purpose and without fee is hereby granted,
40 1.1 reinoud * provided that the above copyright notice appear in all copies and that
41 1.1 reinoud * both that copyright notice and this permission notice appear in
42 1.1 reinoud * supporting documentation, and that the name of Digital Equipment
43 1.1 reinoud * Corporation not be used in advertising or publicity pertaining to
44 1.1 reinoud * distribution of the software without specific, written prior permission.
45 1.1 reinoud *
46 1.1 reinoud *
47 1.1 reinoud * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48 1.1 reinoud * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49 1.1 reinoud * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50 1.1 reinoud * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51 1.1 reinoud * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52 1.1 reinoud * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 1.1 reinoud * SOFTWARE.
54 1.1 reinoud */
55 1.1 reinoud
56 1.1 reinoud /*
57 1.1 reinoud * Extracted version from Xterm tailored for NetBSD
58 1.1 reinoud */
59 1.1 reinoud /* resize.c */
60 1.1 reinoud
61 1.1 reinoud #include <stdio.h>
62 1.1 reinoud #include <ctype.h>
63 1.1 reinoud #include <stdlib.h>
64 1.1 reinoud #include <sys/ioctl.h>
65 1.1 reinoud #include <sys/time.h>
66 1.1 reinoud #include <errno.h>
67 1.1 reinoud #include <unistd.h>
68 1.1 reinoud #include <strings.h>
69 1.1 reinoud #include <libgen.h>
70 1.1 reinoud #include <termios.h>
71 1.1 reinoud #include "xstrings.h"
72 1.1 reinoud
73 1.1 reinoud
74 1.1 reinoud /* imported from origional <xterm.h> */
75 1.1 reinoud #define DFT_TERMTYPE "xterm"
76 1.1 reinoud #define UIntClr(dst,bits) dst = dst & (unsigned) ~(bits)
77 1.1 reinoud
78 1.1 reinoud #include <signal.h>
79 1.1 reinoud #include <pwd.h>
80 1.1 reinoud
81 1.1 reinoud #define ESCAPE(string) "\033" string
82 1.1 reinoud
83 1.1 reinoud #define EMULATIONS 2
84 1.1 reinoud #define SUN 1
85 1.1 reinoud #define VT100 0
86 1.1 reinoud
87 1.1 reinoud #define TIMEOUT 10
88 1.1 reinoud
89 1.1 reinoud #define SHELL_UNKNOWN 0
90 1.1 reinoud #define SHELL_C 1
91 1.1 reinoud #define SHELL_BOURNE 2
92 1.1 reinoud /* *INDENT-OFF* */
93 1.1 reinoud static struct {
94 1.1 reinoud const char *name;
95 1.1 reinoud int type;
96 1.1 reinoud } shell_list[] = {
97 1.1 reinoud { "csh", SHELL_C }, /* vanilla cshell */
98 1.1 reinoud { "jcsh", SHELL_C },
99 1.1 reinoud { "tcsh", SHELL_C },
100 1.1 reinoud { "sh", SHELL_BOURNE }, /* vanilla Bourne shell */
101 1.1 reinoud { "ash", SHELL_BOURNE },
102 1.1 reinoud { "bash", SHELL_BOURNE }, /* GNU Bourne again shell */
103 1.1 reinoud { "dash", SHELL_BOURNE },
104 1.1 reinoud { "jsh", SHELL_BOURNE },
105 1.1 reinoud { "ksh", SHELL_BOURNE }, /* Korn shell (from AT&T toolchest) */
106 1.1 reinoud { "ksh-i", SHELL_BOURNE }, /* another name for Korn shell */
107 1.1 reinoud { "ksh93", SHELL_BOURNE }, /* Korn shell */
108 1.1 reinoud { "mksh", SHELL_BOURNE },
109 1.1 reinoud { "pdksh", SHELL_BOURNE },
110 1.1 reinoud { "zsh", SHELL_BOURNE },
111 1.1 reinoud { NULL, SHELL_BOURNE } /* default (same as xterm's) */
112 1.1 reinoud };
113 1.1 reinoud /* *INDENT-ON* */
114 1.1 reinoud
115 1.1 reinoud static const char *const emuname[EMULATIONS] =
116 1.1 reinoud {
117 1.1 reinoud "VT100",
118 1.1 reinoud "Sun",
119 1.1 reinoud };
120 1.1 reinoud static char *myname;
121 1.1 reinoud static int shell_type = SHELL_UNKNOWN;
122 1.1 reinoud static const char *const getsize[EMULATIONS] =
123 1.1 reinoud {
124 1.1 reinoud ESCAPE("7") ESCAPE("[r") ESCAPE("[9999;9999H") ESCAPE("[6n"),
125 1.1 reinoud ESCAPE("[18t"),
126 1.1 reinoud };
127 1.1 reinoud static const char *const restore[EMULATIONS] =
128 1.1 reinoud {
129 1.1 reinoud ESCAPE("8"),
130 1.1 reinoud 0,
131 1.1 reinoud };
132 1.1 reinoud static const char *const setsize[EMULATIONS] =
133 1.1 reinoud {
134 1.1 reinoud 0,
135 1.1 reinoud ESCAPE("[8;%s;%st"),
136 1.1 reinoud };
137 1.1 reinoud
138 1.1 reinoud static struct termios tioorig;
139 1.1 reinoud
140 1.1 reinoud static const char *const size[EMULATIONS] =
141 1.1 reinoud {
142 1.1 reinoud ESCAPE("[%d;%dR"),
143 1.1 reinoud ESCAPE("[8;%d;%dt"),
144 1.1 reinoud };
145 1.1 reinoud static const char sunname[] = "sunsize";
146 1.1 reinoud static int tty;
147 1.1 reinoud static FILE *ttyfp;
148 1.1 reinoud
149 1.1 reinoud
150 1.1 reinoud static void
151 1.1 reinoud failed(const char *s)
152 1.1 reinoud {
153 1.1 reinoud int save = errno;
154 1.1 reinoud IGNORE_RC(write(2, myname, strlen(myname)));
155 1.1 reinoud IGNORE_RC(write(2, ": ", (size_t) 2));
156 1.1 reinoud errno = save;
157 1.1 reinoud perror(s);
158 1.1 reinoud exit(EXIT_FAILURE);
159 1.1 reinoud }
160 1.1 reinoud
161 1.1 reinoud /* ARGSUSED */
162 1.1 reinoud static void
163 1.1 reinoud onintr(int sig GCC_UNUSED)
164 1.1 reinoud {
165 1.1 reinoud (void) tcsetattr(tty, TCSADRAIN, &tioorig);
166 1.1 reinoud exit(EXIT_FAILURE);
167 1.1 reinoud }
168 1.1 reinoud
169 1.1 reinoud static void
170 1.1 reinoud resize_timeout(int sig)
171 1.1 reinoud {
172 1.1 reinoud fprintf(stderr, "\n%s: Time out occurred\r\n", myname);
173 1.1 reinoud onintr(sig);
174 1.1 reinoud }
175 1.1 reinoud
176 1.1 reinoud static void
177 1.1 reinoud Usage(void)
178 1.1 reinoud {
179 1.1 reinoud fprintf(stderr, strcmp(myname, sunname) == 0 ?
180 1.1 reinoud "Usage: %s [rows cols]\n" :
181 1.1 reinoud "Usage: %s [-v] [-u] [-c] [-s [rows cols]]\n", myname);
182 1.1 reinoud exit(EXIT_FAILURE);
183 1.1 reinoud }
184 1.1 reinoud
185 1.1 reinoud
186 1.1 reinoud static int
187 1.1 reinoud checkdigits(char *str)
188 1.1 reinoud {
189 1.1 reinoud while (*str) {
190 1.1 reinoud if (!isdigit(CharOf(*str)))
191 1.1 reinoud return (0);
192 1.1 reinoud str++;
193 1.1 reinoud }
194 1.1 reinoud return (1);
195 1.1 reinoud }
196 1.1 reinoud
197 1.1 reinoud static void
198 1.1 reinoud readstring(FILE *fp, char *buf, const char *str)
199 1.1 reinoud {
200 1.1 reinoud int last, c;
201 1.1 reinoud struct itimerval it;
202 1.1 reinoud
203 1.1 reinoud signal(SIGALRM, resize_timeout);
204 1.1 reinoud memset((char *) &it, 0, sizeof(struct itimerval));
205 1.1 reinoud it.it_value.tv_sec = TIMEOUT;
206 1.1 reinoud setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL);
207 1.1 reinoud if ((c = getc(fp)) == 0233) { /* meta-escape, CSI */
208 1.1 reinoud c = ESCAPE("")[0];
209 1.1 reinoud *buf++ = (char) c;
210 1.1 reinoud *buf++ = '[';
211 1.1 reinoud } else {
212 1.1 reinoud *buf++ = (char) c;
213 1.1 reinoud }
214 1.1 reinoud if (c != *str) {
215 1.1 reinoud fprintf(stderr, "%s: unknown character, exiting.\r\n", myname);
216 1.1 reinoud onintr(0);
217 1.1 reinoud }
218 1.1 reinoud last = str[strlen(str) - 1];
219 1.1 reinoud while ((*buf++ = (char) getc(fp)) != last) {
220 1.1 reinoud ;
221 1.1 reinoud }
222 1.1 reinoud memset((char *) &it, 0, sizeof(struct itimerval));
223 1.1 reinoud setitimer(ITIMER_REAL, &it, (struct itimerval *) NULL);
224 1.1 reinoud *buf = 0;
225 1.1 reinoud }
226 1.1 reinoud
227 1.1 reinoud /*
228 1.1 reinoud resets termcap string to reflect current screen size
229 1.1 reinoud */
230 1.1 reinoud int
231 1.1 reinoud main(int argc, char **argv ENVP_ARG)
232 1.1 reinoud {
233 1.1 reinoud char *ptr;
234 1.1 reinoud int emu = VT100;
235 1.1 reinoud char *shell;
236 1.1 reinoud int i;
237 1.1 reinoud int rc;
238 1.1 reinoud int rows, cols;
239 1.1 reinoud struct termios tio;
240 1.1 reinoud char buf[BUFSIZ];
241 1.1 reinoud char *name_of_tty;
242 1.1 reinoud const char *setname = "";
243 1.1 reinoud
244 1.1 reinoud myname = x_basename(argv[0]);
245 1.1 reinoud if (strcmp(myname, sunname) == 0)
246 1.1 reinoud emu = SUN;
247 1.1 reinoud for (argv++, argc--; argc > 0 && **argv == '-'; argv++, argc--) {
248 1.1 reinoud switch ((*argv)[1]) {
249 1.1 reinoud case 's': /* Sun emulation */
250 1.1 reinoud if (emu == SUN)
251 1.1 reinoud Usage(); /* Never returns */
252 1.1 reinoud emu = SUN;
253 1.1 reinoud break;
254 1.1 reinoud case 'u': /* Bourne (Unix) shell */
255 1.1 reinoud shell_type = SHELL_BOURNE;
256 1.1 reinoud break;
257 1.1 reinoud case 'c': /* C shell */
258 1.1 reinoud shell_type = SHELL_C;
259 1.1 reinoud break;
260 1.1 reinoud case 'v':
261 1.1 reinoud printf("Xterm(330)\n");
262 1.1 reinoud exit(EXIT_SUCCESS);
263 1.1 reinoud default:
264 1.1 reinoud Usage(); /* Never returns */
265 1.1 reinoud }
266 1.1 reinoud }
267 1.1 reinoud
268 1.1 reinoud if (SHELL_UNKNOWN == shell_type) {
269 1.1 reinoud /* Find out what kind of shell this user is running.
270 1.1 reinoud * This is the same algorithm that xterm uses.
271 1.1 reinoud */
272 1.1 reinoud if ((ptr = x_getenv("SHELL")) == NULL) {
273 1.1 reinoud uid_t uid = getuid();
274 1.1 reinoud struct passwd pw;
275 1.1 reinoud
276 1.1 reinoud if (x_getpwuid(uid, &pw)) {
277 1.1 reinoud (void) x_getlogin(uid, &pw);
278 1.1 reinoud }
279 1.1 reinoud if (!OkPasswd(&pw)
280 1.1 reinoud || *(ptr = pw.pw_shell) == 0) {
281 1.1 reinoud /* this is the same default that xterm uses */
282 1.1 reinoud ptr = x_strdup("/bin/sh");
283 1.1 reinoud }
284 1.1 reinoud }
285 1.1 reinoud
286 1.1 reinoud shell = x_basename(ptr);
287 1.1 reinoud
288 1.1 reinoud /* now that we know, what kind is it? */
289 1.1 reinoud for (i = 0; shell_list[i].name; i++) {
290 1.1 reinoud if (!strcmp(shell_list[i].name, shell)) {
291 1.1 reinoud break;
292 1.1 reinoud }
293 1.1 reinoud }
294 1.1 reinoud shell_type = shell_list[i].type;
295 1.1 reinoud }
296 1.1 reinoud
297 1.1 reinoud if (argc == 2) {
298 1.1 reinoud if (!setsize[emu]) {
299 1.1 reinoud fprintf(stderr,
300 1.1 reinoud "%s: Can't set window size under %s emulation\n",
301 1.1 reinoud myname, emuname[emu]);
302 1.1 reinoud exit(EXIT_FAILURE);
303 1.1 reinoud }
304 1.1 reinoud if (!checkdigits(argv[0]) || !checkdigits(argv[1])) {
305 1.1 reinoud Usage(); /* Never returns */
306 1.1 reinoud }
307 1.1 reinoud } else if (argc != 0) {
308 1.1 reinoud Usage(); /* Never returns */
309 1.1 reinoud }
310 1.1 reinoud name_of_tty = x_strdup("/dev/tty");
311 1.1 reinoud
312 1.1 reinoud if ((ttyfp = fopen(name_of_tty, "r+")) == NULL) {
313 1.1 reinoud fprintf(stderr, "%s: can't open terminal %s\n",
314 1.1 reinoud myname, name_of_tty);
315 1.1 reinoud exit(EXIT_FAILURE);
316 1.1 reinoud }
317 1.1 reinoud tty = fileno(ttyfp);
318 1.1 reinoud if (x_getenv("TERM") == 0) {
319 1.1 reinoud if (SHELL_BOURNE == shell_type) {
320 1.1 reinoud setname = "TERM=" DFT_TERMTYPE ";\nexport TERM;\n";
321 1.1 reinoud } else {
322 1.1 reinoud setname = "setenv TERM " DFT_TERMTYPE ";\n";
323 1.1 reinoud }
324 1.1 reinoud }
325 1.1 reinoud
326 1.1 reinoud rc = tcgetattr(tty, &tioorig);
327 1.1 reinoud tio = tioorig;
328 1.1 reinoud UIntClr(tio.c_iflag, ICRNL);
329 1.1 reinoud UIntClr(tio.c_lflag, (ICANON | ECHO));
330 1.1 reinoud tio.c_cflag |= CS8;
331 1.1 reinoud tio.c_cc[VMIN] = 6;
332 1.1 reinoud tio.c_cc[VTIME] = 1;
333 1.1 reinoud if (rc != 0)
334 1.1 reinoud failed("get tty settings");
335 1.1 reinoud
336 1.1 reinoud signal(SIGINT, onintr);
337 1.1 reinoud signal(SIGQUIT, onintr);
338 1.1 reinoud signal(SIGTERM, onintr);
339 1.1 reinoud
340 1.1 reinoud rc = tcsetattr(tty, TCSADRAIN, &tio);
341 1.1 reinoud if (rc != 0)
342 1.1 reinoud failed("set tty settings");
343 1.1 reinoud
344 1.1 reinoud if (argc == 2) { /* look for optional parameters of "-s" */
345 1.1 reinoud char *tmpbuf = TypeMallocN(char,
346 1.1 reinoud strlen(setsize[emu]) +
347 1.1 reinoud strlen(argv[0]) +
348 1.1 reinoud strlen(argv[1]) +
349 1.1 reinoud 1);
350 1.1 reinoud if (tmpbuf == 0) {
351 1.1 reinoud fprintf(stderr, "%s: Cannot query size\n", myname);
352 1.1 reinoud onintr(0);
353 1.1 reinoud } else {
354 1.1 reinoud sprintf(tmpbuf, setsize[emu], argv[0], argv[1]);
355 1.1 reinoud IGNORE_RC(write(tty, tmpbuf, strlen(tmpbuf)));
356 1.1 reinoud free(tmpbuf);
357 1.1 reinoud }
358 1.1 reinoud }
359 1.1 reinoud IGNORE_RC(write(tty, getsize[emu], strlen(getsize[emu])));
360 1.1 reinoud readstring(ttyfp, buf, size[emu]);
361 1.1 reinoud if (sscanf(buf, size[emu], &rows, &cols) != 2) {
362 1.1 reinoud fprintf(stderr, "%s: Can't get rows and columns\r\n", myname);
363 1.1 reinoud onintr(0);
364 1.1 reinoud }
365 1.1 reinoud if (restore[emu])
366 1.1 reinoud IGNORE_RC(write(tty, restore[emu], strlen(restore[emu])));
367 1.1 reinoud
368 1.1 reinoud rc = tcsetattr(tty, TCSADRAIN, &tioorig);
369 1.1 reinoud if (rc != 0)
370 1.1 reinoud failed("set tty settings");
371 1.1 reinoud
372 1.1 reinoud signal(SIGINT, SIG_DFL);
373 1.1 reinoud signal(SIGQUIT, SIG_DFL);
374 1.1 reinoud signal(SIGTERM, SIG_DFL);
375 1.1 reinoud
376 1.1 reinoud
377 1.1 reinoud if (SHELL_BOURNE == shell_type) {
378 1.1 reinoud
379 1.1 reinoud printf("%sCOLUMNS=%d;\nLINES=%d;\nexport COLUMNS LINES;\n",
380 1.1 reinoud setname, cols, rows);
381 1.1 reinoud
382 1.1 reinoud } else { /* not Bourne shell */
383 1.1 reinoud
384 1.1 reinoud printf("set noglob;\n%ssetenv COLUMNS '%d';\nsetenv LINES '%d';\nunset noglob;\n",
385 1.1 reinoud setname, cols, rows);
386 1.1 reinoud }
387 1.1 reinoud exit(EXIT_SUCCESS);
388 1.1 reinoud }
389