1 /* machmgr.c
2 *
3 * Omnitty SSH Multiplexer
4 * Copyright (c) 2004 Bruno Takahashi C. de Oliveira
5 * All rights reserved.
6 *
7 * LICENSE INFORMATION:
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Copyright (c) 2002 Bruno T. C. de Oliveira
22 */
23
24 #include "machmgr.h"
25 #include "curutil.h"
26 #include "machine.h"
27 #include "minibuf.h"
28 #include <string.h>
29 #include <stdlib.h>
30
31 #define MACHINE_MAX 256
32
33 /* List of machines */
34 static Machine *machs[MACHINE_MAX];
35 static int machcount = 0;
36 static int selmach = 0; /* currently selected machine */
37 static int scrollpos = 0; /* machine being shown at the top of the list */
38 static int vtrows, vtcols;
39 bool multicast = false; /* whether keystrokes are sent to all tagged
40 * machines or not */
41 static WINDOW *listwin;
42
machmgr_init(WINDOW * lw,int vtr,int vtc)43 void machmgr_init(WINDOW *lw, int vtr, int vtc) {
44 machcount = selmach = scrollpos = 0;
45 vtrows = vtr, vtcols = vtc;
46 listwin = lw;
47 }
48
machmgr_setselmach(int s)49 static void machmgr_setselmach(int s) {
50 int screenwidth, screenheight;
51 getmaxyx(listwin, screenheight, screenwidth);
52
53 selmach = s;
54
55 /* clamp selmach to bounds */
56 if (selmach >= machcount) selmach = machcount - 1;
57 if (selmach < 0) selmach = 0;
58
59 /* in particular, if machcount == 0, selmach will be 0 */
60
61 /* correct scrolling if needed */
62 if (machcount > 0) {
63 if (selmach < scrollpos) scrollpos = selmach;
64 if (selmach >= scrollpos + screenheight)
65 scrollpos = selmach - screenheight + 1;
66 }
67 }
68
machmgr_selmach_validate()69 static void machmgr_selmach_validate() {
70 machmgr_setselmach(selmach);
71 }
72
machmgr_draw_list()73 void machmgr_draw_list() {
74 unsigned char attr;
75 const char *p;
76 int w, h;
77 int i, j;
78
79 werase(listwin);
80 getmaxyx(listwin, h, w);
81
82 for (i = scrollpos; i < scrollpos + h && i < machcount; i++) {
83 /* decide color */
84 attr = machs[i]->alive ? 0x70 : 0x80;
85 if (i == selmach) attr &= 0xF0, attr |= 0x01; /* red background */
86 if (machs[i]->tag) attr &= 0x0F, attr |= machs[i]->alive ? 0xA0 : 0x20;
87 /* green foreground */
88
89 curutil_attrset(listwin, attr);
90 wmove(listwin, i - scrollpos, 0);
91
92 waddch(listwin, machs[i]->tag ? '*' : ' ');
93
94 /* now we have to print the first w-2 characters of machs[i]->name,
95 * padding with spaces at the end if necessary to complete w-2
96 * characters. We say w-2 because one character of the width was
97 * used up when printing '*' and another one must be left blank
98 * at the end */
99 p = machs[i]->name; j = w - 2;
100 while (j--) {
101 waddch(listwin, *p ? *p : ' ');
102 if (*p) p++;
103 }
104 }
105 }
106
machmgr_add(const char * machname)107 void machmgr_add(const char *machname) {
108 if (!*machname) return;
109 if (machcount >= MACHINE_MAX) return;
110 machs[machcount++] = machine_new(machname, vtrows, vtcols);
111 machmgr_selmach_validate();
112 }
113
machmgr_delete(int index)114 static void machmgr_delete(int index) {
115 int i;
116 if (index < 0 || index >= machcount) return;
117
118 machine_destroy(machs[index]);
119 for (i = index; i < machcount - 1; i++) machs[i] = machs[i+1];
120 machcount--;
121
122 machmgr_selmach_validate();
123 }
124
machmgr_delete_tagged()125 void machmgr_delete_tagged() {
126 int i, j;
127
128 i = 0; /* next position in the vector we will write to */
129 j = 0; /* next position in the vector we will look at in search
130 * of nontagged machines */
131 while (j < machcount) {
132 /* advance j to the next untagged machine; finish if no such thing.
133 * Delete tagged machines on the way. */
134 while (j < machcount && machs[j]->tag) machine_destroy(machs[j++]);
135
136 if (j >= machcount) break; /* no more machines */
137 machs[i++] = machs[j++];
138 }
139
140 machcount = i;
141 machmgr_selmach_validate();
142 }
143
machmgr_delete_current()144 void machmgr_delete_current() {
145 machmgr_delete(selmach);
146 }
147
make_vt_summary(RoteTerm * rt,char * buf,int len)148 static void make_vt_summary(RoteTerm *rt, char *buf, int len) {
149 int r = rt->crow, c = rt->ccol;
150 int i;
151
152 buf[len-1] = 0;
153 for (i = len - 2; i >= 0; i--) {
154 if (r > 0) {
155 buf[i] = rt->cells[r][c].ch;
156 if ((buf[i] >= 0 && buf[i] < 32) || buf[i] == 127) buf[i] = 32;
157 }
158 else buf[i] = 32;
159
160 if (--c < 0) {
161 r--, c = rt->cols - 1;
162 if (r > 0) while (c > 0 && rt->cells[r][c-1].ch == 32) c--;
163 }
164 }
165 }
166
machmgr_draw_summary(WINDOW * w)167 void machmgr_draw_summary(WINDOW *w) {
168 int i;
169 int sumheight, sumwidth;
170 char sumbuf[80];
171 werase(w);
172 wmove(w, 0, 0);
173 getmaxyx(w, sumheight, sumwidth);
174
175 for (i = scrollpos; i < scrollpos + sumheight && i < machcount; i++) {
176 curutil_attrset(w, 0x80);
177 wmove(w, i - scrollpos, 0);
178
179 make_vt_summary(machs[i]->vt, sumbuf, sumwidth);
180 waddstr(w, sumbuf);
181 }
182 }
183
machmgr_draw_vt(WINDOW * w)184 void machmgr_draw_vt(WINDOW *w) {
185 werase(w);
186 if (selmach >= 0 && selmach < machcount)
187 rote_vt_draw(machs[selmach]->vt, w, 0, 0, NULL);
188 }
189
machmgr_update()190 void machmgr_update() {
191 int i;
192 for (i = 0; i < machcount; i++)
193 rote_vt_update(machs[i]->vt);
194 }
195
machmgr_rename(char * newname)196 void machmgr_rename(char *newname) {
197 machine_rename(machs[selmach], newname);
198 machmgr_update();
199 }
200
machmgr_prev_machine()201 void machmgr_prev_machine() {
202 machmgr_setselmach(selmach - 1);
203 }
204
machmgr_next_machine()205 void machmgr_next_machine() {
206 machmgr_setselmach(selmach + 1);
207 }
208
machmgr_forward_keypress(int k)209 void machmgr_forward_keypress(int k) {
210 int i;
211
212 if (multicast) {
213 for (i = 0; i < machcount; i++)
214 if (machs[i]->tag) rote_vt_keypress(machs[i]->vt, k);
215 }
216 else if (selmach >= 0 && selmach < machcount)
217 rote_vt_keypress(machs[selmach]->vt, k);
218 }
219
machmgr_handle_death(pid_t p)220 void machmgr_handle_death(pid_t p) {
221 int i;
222 for (i = 0; i < machcount; i++) {
223 if (machs[i]->pid == p) {
224 machs[i]->alive = false;
225 rote_vt_forsake_child(machs[i]->vt);
226 }
227 }
228 }
229
machmgr_toggle_multicast()230 void machmgr_toggle_multicast() {
231 multicast = !multicast;
232 }
233
machmgr_is_multicast()234 bool machmgr_is_multicast() {
235 return multicast;
236 }
237
machmgr_toggle_tag_current()238 void machmgr_toggle_tag_current() {
239 if (selmach >= 0 && selmach < machcount)
240 machs[selmach]->tag = !machs[selmach]->tag;
241 }
242
machmgr_delete_all()243 void machmgr_delete_all() {
244 int i;
245 for (i = 0; i < machcount; i++) machine_destroy(machs[i]);
246 machcount = selmach = scrollpos = 0;
247 }
248
machmgr_tag_all(bool ignore_dead)249 void machmgr_tag_all(bool ignore_dead) {
250 int i;
251 for (i = 0; i < machcount; i++)
252 machs[i]->tag = (!ignore_dead || machs[i]->alive);
253 }
254
machmgr_untag_all()255 void machmgr_untag_all() {
256 int i;
257 for (i = 0; i < machcount; i++) machs[i]->tag = false;
258 }
259
machmgr_delete_dead()260 void machmgr_delete_dead() {
261 int i;
262 for (i = machcount - 1; i >= 0; i--)
263 if (!machs[i]->alive) machmgr_delete(i);
264 }
265
machmgr_toggle_tag_all(bool ignore_dead)266 void machmgr_toggle_tag_all(bool ignore_dead) {
267 int i;
268 for (i = 0; i < machcount; i++) {
269 if (!ignore_dead || machs[i]->alive)
270 machs[i]->tag = !machs[i]->tag;
271 }
272 }
273
274