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