1 /*	$OpenBSD: lcmd1.c,v 1.9 2003/07/18 23:11:43 david Exp $	*/
2 /*	$NetBSD: lcmd1.c,v 1.6 1996/02/08 20:45:00 mycroft Exp $	*/
3 
4 /*
5  * Copyright (c) 1983, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Edward Wang at The University of California, Berkeley.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)lcmd1.c	8.1 (Berkeley) 6/6/93";
39 #else
40 static char rcsid[] = "$OpenBSD: lcmd1.c,v 1.9 2003/07/18 23:11:43 david Exp $";
41 #endif
42 #endif /* not lint */
43 
44 #include "defs.h"
45 #include "string.h"
46 #include "value.h"
47 #include "lcmd.h"
48 #include "var.h"
49 #include <sys/types.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <unistd.h>
53 
54 struct lcmd_arg arg_window[] = {
55 	{ "row",	1,	ARG_NUM },
56 	{ "column",	1,	ARG_NUM },
57 	{ "nrows",	2,	ARG_NUM },
58 	{ "ncols",	2,	ARG_NUM },
59 	{ "nlines",	2,	ARG_NUM },
60 	{ "label",	1,	ARG_STR },
61 	{ "pty",	1,	ARG_ANY },
62 	{ "frame",	1,	ARG_ANY },
63 	{ "mapnl",	1,	ARG_ANY },
64 	{ "keepopen",	1,	ARG_ANY },
65 	{ "smooth",	1,	ARG_ANY },
66 	{ "shell",	1,	ARG_STR|ARG_LIST },
67 	0
68 };
69 
70 l_window(v, a)
71 struct value *v;
72 struct value *a;
73 {
74 	struct ww *w;
75 	int col, row, ncol, nrow, id, nline;
76 	char *label;
77 	int haspty, hasframe, mapnl, keepopen, smooth;
78 	char *shf, **sh;
79 	char *argv[sizeof default_shell / sizeof *default_shell];
80 	char **pp;
81 
82 	if ((id = findid()) < 0)
83 		return;
84 	row = a->v_type == V_ERR ? 1 : a->v_num;
85 	a++;
86 	col = a->v_type == V_ERR ? 0 : a->v_num;
87 	a++;
88 	nrow = a->v_type == V_ERR ? wwnrow - row : a->v_num;
89 	a++;
90 	ncol = a->v_type == V_ERR ? wwncol - col : a->v_num;
91 	a++;
92 	nline = a->v_type == V_ERR ? default_nline : a->v_num;
93 	a++;
94 	label = a->v_type == V_ERR ? 0 : a->v_str;
95 	if ((haspty = vtobool(++a, 1, -1)) < 0)
96 		return;
97 	if ((hasframe = vtobool(++a, 1, -1)) < 0)
98 		return;
99 	if ((mapnl = vtobool(++a, !haspty, -1)) < 0)
100 		return;
101 	if ((keepopen = vtobool(++a, 0, -1)) < 0)
102 		return;
103 	if ((smooth = vtobool(++a, default_smooth, -1)) < 0)
104 		return;
105 	if ((++a)->v_type != V_ERR) {
106 		for (pp = argv; a->v_type != V_ERR &&
107 		     pp < &argv[sizeof argv/sizeof *argv-1]; pp++, a++)
108 			*pp = a->v_str;
109 		*pp = 0;
110 		shf = *(sh = argv);
111 		if (*sh = strrchr(shf, '/'))
112 			(*sh)++;
113 		else
114 			*sh = shf;
115 	} else {
116 		sh = default_shell;
117 		shf = default_shellfile;
118 	}
119 	if ((w = openwin(id, row, col, nrow, ncol, nline, label,
120 	    haspty ? WWT_PTY : WWT_SOCKET, hasframe ? WWU_HASFRAME : 0, shf,
121 	    sh)) == 0)
122 		return;
123 	if (mapnl)
124 		SET(w->ww_wflags, WWW_MAPNL);
125 	else
126 		CLR(w->ww_wflags, WWW_MAPNL);
127 	if (keepopen)
128 		SET(w->ww_uflags, WWU_KEEPOPEN);
129 	else
130 		CLR(w->ww_uflags, WWU_KEEPOPEN);
131 	if (!smooth)
132 		SET(w->ww_wflags, WWW_NOUPDATE);
133 	else
134 		CLR(w->ww_wflags, WWW_NOUPDATE);
135 	v->v_type = V_NUM;
136 	v->v_num = id + 1;
137 }
138 
139 struct lcmd_arg arg_def_nline[] = {
140 	{ "nlines",	1,	ARG_NUM },
141 	0
142 };
143 
144 l_def_nline(v, a)
145 struct value *v, *a;
146 {
147 	v->v_num = default_nline;
148 	v->v_type = V_NUM;
149 	if (a->v_type != V_ERR)
150 		default_nline = a->v_num;
151 }
152 
153 struct lcmd_arg arg_smooth[] = {
154 	{ "window",	1,	ARG_NUM },
155 	{ "flag",	1,	ARG_ANY },
156 	0
157 };
158 
159 l_smooth(v, a)
160 struct value *v, *a;
161 {
162 	struct ww *w;
163 
164 	v->v_type = V_NUM;
165 	v->v_num = 0;
166 	if ((w = vtowin(a++, selwin)) == 0)
167 		return;
168 	v->v_num = ISSET(w->ww_wflags, WWW_NOUPDATE) == 0;
169 	if (!vtobool(a, v->v_num, v->v_num))
170 		SET(w->ww_wflags, WWW_NOUPDATE);
171 	else
172 		CLR(w->ww_wflags, WWW_NOUPDATE);
173 }
174 
175 struct lcmd_arg arg_def_smooth[] = {
176 	{ "flag",	1,	ARG_ANY },
177 	0
178 };
179 
180 l_def_smooth(v, a)
181 struct value *v, *a;
182 {
183 	v->v_type = V_NUM;
184 	v->v_num = default_smooth;
185 	default_smooth = vtobool(a, v->v_num, v->v_num);
186 }
187 
188 struct lcmd_arg arg_select[] = {
189 	{ "window",	1,	ARG_NUM },
190 	0
191 };
192 
193 l_select(v, a)
194 struct value *v, *a;
195 {
196 	struct ww *w;
197 
198 	v->v_type = V_NUM;
199 	v->v_num = selwin ? selwin->ww_id + 1 : -1;
200 	if (a->v_type == V_ERR)
201 		return;
202 	if ((w = vtowin(a, (struct ww *)0)) == 0)
203 		return;
204 	setselwin(w);
205 }
206 
207 struct lcmd_arg arg_debug[] = {
208 	{ "flag",	1,	ARG_ANY },
209 	0
210 };
211 
212 l_debug(v, a)
213 struct value *v, *a;
214 {
215 	v->v_type = V_NUM;
216 	v->v_num = debug;
217 	debug = vtobool(a, debug, debug);
218 }
219 
220 struct lcmd_arg arg_escape[] = {
221 	{ "escapec",	1,	ARG_STR },
222 	0
223 };
224 
225 l_escape(v, a)
226 struct value *v, *a;
227 {
228 	char buf[2];
229 
230 	buf[0] = escapec;
231 	buf[1] = 0;
232 	if ((v->v_str = str_cpy(buf)) == 0) {
233 		error("Out of memory.");
234 		return;
235 	}
236 	v->v_type = V_STR;
237 	if (a->v_type != V_ERR)
238 		setescape(a->v_str);
239 }
240 
241 struct lcmd_arg arg_label[] = {
242 	{ "window",	1,	ARG_NUM },
243 	{ "label",	1,	ARG_STR },
244 	0
245 };
246 
247 /*ARGSUSED*/
248 l_label(v, a)
249 struct value *v;
250 struct value *a;
251 {
252 	struct ww *w;
253 
254 	if ((w = vtowin(a, selwin)) == 0)
255 		return;
256 	if ((++a)->v_type != V_ERR && setlabel(w, a->v_str) < 0)
257 		error("Out of memory.");
258 	reframe();
259 }
260 
261 struct lcmd_arg arg_foreground[] = {
262 	{ "window",	1,	ARG_NUM },
263 	{ "flag",	1,	ARG_ANY },
264 	0
265 };
266 
267 l_foreground(v, a)
268 struct value *v, *a;
269 {
270 	struct ww *w;
271 	char flag;
272 
273 	if ((w = vtowin(a, selwin)) == 0)
274 		return;
275 	v->v_type = V_NUM;
276 	v->v_num = isfg(w);
277 	flag = vtobool(++a, v->v_num, v->v_num);
278 	if (flag == v->v_num)
279 		return;
280 	deletewin(w);
281 	addwin(w, flag);
282 	reframe();
283 }
284 
285 struct lcmd_arg arg_terse[] = {
286 	{ "flag",	1,	ARG_ANY },
287 	0
288 };
289 
290 l_terse(v, a)
291 struct value *v, *a;
292 {
293 	v->v_type = V_NUM;
294 	v->v_num = terse;
295 	setterse(vtobool(a, terse, terse));
296 }
297 
298 struct lcmd_arg arg_source[] = {
299 	{ "filename",	1,	ARG_STR },
300 	0
301 };
302 
303 l_source(v, a)
304 struct value *v, *a;
305 {
306 	v->v_type = V_NUM;
307 	if (a->v_type != V_ERR && dosource(a->v_str) < 0) {
308 		error("Can't open %s.", a->v_str);
309 		v->v_num = -1;
310 	} else
311 		v->v_num = 0;
312 }
313 
314 struct lcmd_arg arg_write[] = {
315 	{ "window",	1,	ARG_NUM },
316 	{ "",		0,	ARG_ANY|ARG_LIST },
317 	0
318 };
319 
320 /*ARGSUSED*/
321 l_write(v, a)
322 struct value *v;
323 struct value *a;
324 {
325 	char buf[20];
326 	struct ww *w;
327 
328 	if ((w = vtowin(a++, selwin)) == 0)
329 		return;
330 	while (a->v_type != V_ERR) {
331 		if (a->v_type == V_NUM) {
332 			(void) snprintf(buf, sizeof(buf), "%d", a->v_num);
333 			(void) write(w->ww_pty, buf, strlen(buf));
334 		} else
335 			(void) write(w->ww_pty, a->v_str, strlen(a->v_str));
336 		if ((++a)->v_type != V_ERR)
337 			(void) write(w->ww_pty, " ", 1);
338 	}
339 }
340 
341 struct lcmd_arg arg_close[] = {
342 	{ "window",	1,	ARG_ANY|ARG_LIST },
343 	0
344 };
345 
346 /*ARGSUSED*/
347 l_close(v, a)
348 struct value *v;
349 struct value *a;
350 {
351 	struct ww *w;
352 
353 	if (a->v_type == V_STR && str_match(a->v_str, "all", 3))
354 		closewin((struct ww *)0);
355 	else
356 		for (; a->v_type != V_ERR; a++)
357 			if ((w = vtowin(a, (struct ww *)0)) != 0)
358 				closewin(w);
359 }
360 
361 struct lcmd_arg arg_cursormodes[] = {
362 	{ "modes",	1,	ARG_NUM },
363 	0
364 };
365 
366 l_cursormodes(v, a)
367 struct value *v, *a;
368 {
369 
370 	v->v_type = V_NUM;
371 	v->v_num = wwcursormodes;
372 	if (a->v_type != V_ERR)
373 		wwsetcursormodes(a->v_num);
374 }
375 
376 struct lcmd_arg arg_unset[] = {
377 	{ "variable",	1,	ARG_ANY },
378 	0
379 };
380 
381 l_unset(v, a)
382 struct value *v, *a;
383 {
384 	v->v_type = V_NUM;
385 	switch (a->v_type) {
386 	case V_ERR:
387 		v->v_num = -1;
388 		return;
389 	case V_NUM:
390 		if ((a->v_str = str_itoa(a->v_num)) == 0) {
391 			error("Out of memory.");
392 			v->v_num = -1;
393 			return;
394 		}
395 		a->v_type = V_STR;
396 		break;
397 	}
398 	v->v_num = var_unset(a->v_str);
399 }
400 
401 struct ww *
vtowin(v,w)402 vtowin(v, w)
403 struct value *v;
404 struct ww *w;
405 {
406 	switch (v->v_type) {
407 	case V_ERR:
408 		if (w != 0)
409 			return w;
410 		error("No window specified.");
411 		return 0;
412 	case V_STR:
413 		error("%s: No such window.", v->v_str);
414 		return 0;
415 	}
416 	if (v->v_num < 1 || v->v_num > NWINDOW
417 	    || (w = window[v->v_num - 1]) == 0) {
418 		error("%d: No such window.", v->v_num);
419 		return 0;
420 	}
421 	return w;
422 }
423 
424 vtobool(v, def, err)
425 struct value *v;
426 char def, err;
427 {
428 	switch (v->v_type) {
429 	case V_NUM:
430 		return v->v_num != 0;
431 	case V_STR:
432 		if (str_match(v->v_str, "true", 1)
433 		    || str_match(v->v_str, "on", 2)
434 		    || str_match(v->v_str, "yes", 1))
435 			return 1;
436 		else if (str_match(v->v_str, "false", 1)
437 		    || str_match(v->v_str, "off", 2)
438 		    || str_match(v->v_str, "no", 1))
439 			return 0;
440 		else {
441 			error("%s: Illegal boolean value.", v->v_str);
442 			return err;
443 		}
444 		/*NOTREACHED*/
445 	case V_ERR:
446 		return def;
447 	}
448 	/*NOTREACHED*/
449 }
450