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