]> andersk Git - moira.git/blame - clients/mmoira/tty.c
punt mrgdb
[moira.git] / clients / mmoira / tty.c
CommitLineData
48a59f6d 1/* $Header$
2 *
3 * Copyright 1992 by the Massachusetts Institute of Technology.
4 *
5 * For further information on copyright and distribution
6 * see the file mit-copyright.h
7 */
8
9#include <mit-copyright.h>
10#include <stdio.h>
698271c7 11#include <string.h>
48a59f6d 12#include <sys/types.h>
13#include <sys/signal.h>
8e1c738c 14#ifdef POSIX
15#include <termios.h>
16#else
48a59f6d 17#include <sgtty.h>
8e1c738c 18#endif
48a59f6d 19#include <sys/ioctl.h>
20#include <ctype.h>
48a59f6d 21#include <X11/Intrinsic.h>
df52b790 22#include <moira.h>
48a59f6d 23#include "mmoira.h"
df52b790 24#include "parser.h"
48a59f6d 25
26static char rcsid[] = "$Header$";
27
28
df52b790 29struct parse_node *TtyCommands = NULL, *TtyRoot = NULL;
48a59f6d 30
31extern int NumMenus;
32extern MenuItem MenuRoot;
33char prompt[] = "moira> ";
34
8e1c738c 35#ifdef POSIX
36static struct termios otty, ntty;
37#else
df52b790 38static struct sgttyb otty, ntty;
8e1c738c 39#endif
48a59f6d 40
41TtyMainLoop()
42{
43 char buf[1024], cbuf[2], c, *p;
44 int arg, i, done;
48a59f6d 45
df52b790 46 if (TtyCommands == NULL)
47 parse_menus();
48
49#ifdef DEBUG
50 print_parse_tree(TtyRoot, 0);
51 fflush(stdout);
52 sleep(10);
53#endif /* DEBUG */
48a59f6d 54
8e1c738c 55#ifdef POSIX
56 tcgetattr(0, &otty);
57 ntty = otty;
58 ntty.c_lflag &= ~(ICANON|ECHO);
59 ntty.c_cc[VTIME] = 0;
60 ntty.c_cc[VMIN] = 1;
61#else
48a59f6d 62 ioctl(0, TIOCFLUSH, &arg);
df52b790 63 ioctl(0, TIOCGETP, &otty);
64 ntty = otty;
48a59f6d 65 ntty.sg_flags |= RAW;
66 ntty.sg_flags &= ~ECHO;
8e1c738c 67#endif
df52b790 68 raw_mode();
48a59f6d 69
70 while (1) {
df52b790 71 parser(prompt, TtyRoot);
48a59f6d 72 }
48a59f6d 73}
74
df52b790 75cooked_mode()
48a59f6d 76{
8e1c738c 77#ifdef POSIX
78 tcsetattr (0, TCSANOW, &otty);
79#else
df52b790 80 ioctl(0, TIOCSETP, &otty);
8e1c738c 81#endif
48a59f6d 82}
83
df52b790 84raw_mode()
48a59f6d 85{
8e1c738c 86#ifdef POSIX
87 tcsetattr (0, TCSANOW, &ntty);
88#else
df52b790 89 ioctl(0, TIOCSETP, &ntty);
8e1c738c 90#endif
48a59f6d 91}
92
48a59f6d 93static NumWords(s)
94char *s;
95{
96 int ret;
97
98 for (ret = 1; *s; s++)
99 if (*s == ' ') ret++;
100 return(ret);
101}
102
103
df52b790 104parse_menus()
48a59f6d 105{
106 int arg;
df52b790 107 struct parse_node *p;
48a59f6d 108
df52b790 109 TtyCommands = (struct parse_node *)malloc(sizeof(struct parse_node) *
110 NumMenus * 3);
698271c7 111 memset(TtyCommands, 0, sizeof(struct parse_node) * NumMenus * 3);
48a59f6d 112 arg = 0;
113 parse_menu_recursive(&MenuRoot, "", &arg);
df52b790 114 TtyCommands[arg].p_word = "help";
115 TtyCommands[arg].p_next = TtyRoot;
116 for (p = TtyRoot; p; p = p->p_peer)
117 if (strcmp(p->p_peer->p_word, "help") > 0)
118 break;
119 TtyCommands[arg].p_peer = p->p_peer->p_peer;
120 p->p_peer = &TtyCommands[arg];
121 arg++;
48a59f6d 122}
123
124
df52b790 125parse_menu_recursive(m, parent, i)
48a59f6d 126MenuItem *m;
127char *parent;
128int *i;
129{
df52b790 130 char buf[64], cmd[64], *word, *s;
48a59f6d 131 struct parse_node *p, **prev;
df52b790 132 int j, len;
48a59f6d 133
134 if (m->submenu == NULL) {
135 if (!strcmp(parent, "file") ||
136 !strcmp(parent, "misc"))
137 parent = "";
df52b790 138 if (NumWords(m->label) > 2 || !*parent)
48a59f6d 139 strcpy(cmd, m->label);
140 else
141 sprintf(cmd, "%s %s", m->label, parent);
142 /* insert command into parse tree */
df52b790 143 p = TtyRoot;
144 prev = (struct parse_node **) &TtyRoot;
698271c7 145 for (word = cmd; word; word = strchr(word, ' ')) {
df52b790 146 if (*word == ' ')
147 word++;
698271c7 148 s = strchr(word, ' ');
48a59f6d 149 if (s)
150 len = s - word;
151 else
152 len = strlen(word);
df52b790 153 for (;;) {
154 if (!p || !p->p_word ||
155 (j = strncmp(p->p_word, word, len)) > 0) {
48a59f6d 156 strcpy(buf, word);
157 buf[len] = 0;
df52b790 158#ifdef DEBUG
159 printf("word: %s\n", buf);
160#endif
48a59f6d 161 TtyCommands[*i].p_word = strsave(buf);
df52b790 162 if (len == strlen(word))
163 TtyCommands[*i].p_menu = m;
48a59f6d 164 TtyCommands[*i].p_peer = p;
165 if (prev)
df52b790 166 *prev = &TtyCommands[*i];
48a59f6d 167 TtyCommands[*i].p_next = (struct parse_node *) NULL;
168 TtyCommands[*i].p_link = (struct parse_node *) NULL;
df52b790 169 prev = &(TtyCommands[*i].p_next);
170 p = (struct parse_node *) NULL;
171 *i = *i + 1;
48a59f6d 172 break;
173 } else if (j == 0) {
174 prev = &(p->p_next);
175 if (p->p_next)
df52b790 176 p = p->p_next;
48a59f6d 177 else
178 p = (struct parse_node *) NULL;
179 break;
180 } else {
181 prev = &(p->p_peer);
df52b790 182 p = p->p_peer;
48a59f6d 183 }
184 }
185 }
48a59f6d 186 return;
187 }
188 if (!strcmp(m->label, "?help")) return;
189 for (j = 0; m->submenu[j]; j++) {
190 if (m == &MenuRoot)
191 buf[0] = 0;
192 else if (strlen(parent))
193 sprintf(buf, "%s %s", parent, m->label);
194 else
195 strcpy(buf, m->label);
196 parse_menu_recursive(m->submenu[j], buf, i);
197 }
198}
199
200
201TtyForm(f)
202EntryForm *f;
203{
df52b790 204 int i, j, done, best, choice;
205 char buf[512], *k;
206 UserPrompt *p;
207
208 printf("%s\r\n", f->instructions);
209 choice = 0;
210 for (i = 0, p = f->inputlines[i]; p = f->inputlines[i]; i++)
211 if (p->choice) {
212 choice = 1;
213 break;
214 }
215 if (choice) {
216 j = 0;
217 *buf = 0;
218 for (i = 0, p = f->inputlines[i]; p = f->inputlines[i]; i++) {
219 if (p->choice) {
220 printf(" %s\r\n", buf);
221 sprintf(buf, "%d: %s", ++j, p->prompt);
222 } else if (*buf == 0) {
223 sprintf(buf, "%d: %s", ++j, p->prompt);
224 } else {
225 strcat(buf, "/");
226 strcat(buf, p->prompt);
227 }
228 if (buf[strlen(buf)-1] == ' ') buf[strlen(buf)-1] = 0;
229 }
230 printf(" %s\r\nSelect by [1]: ", buf);
231 if (mgets(buf, sizeof(buf)))
232 return;
233 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
234 if (strlen(buf) == 0)
235 choice = 1;
236 else
237 choice = atoi(buf);
238 } else choice = -1;
239 for (i = 0, p = f->inputlines[i]; p = f->inputlines[i]; i++) {
240 if (choice > 0 && p->choice) choice--;
241 if (choice != -1 && choice != 1) continue;
242 if (p->insensitive == True) continue;
243 switch (p->type) {
244 case FT_BOOLEAN:
245 done = 0;
246 while (!done) {
247 done = 1;
1b6c52dc 248 printf("%s(T/F) [%c]: ", p->prompt, boolval(f, i) ? 'T' : 'F');
df52b790 249 fflush(stdout);
250 if (mgets(buf, sizeof(buf)))
251 return;
252 if (buf[0] == 'T' || buf[0] == 't' ||
253 buf[0] == 'Y' || buf[0] == 'y')
254 p->returnvalue.booleanvalue = True;
255 else if (buf[0] == 'F' || buf[0] == 'f' ||
256 buf[0] == 'N' || buf[0] == 'n')
257 p->returnvalue.booleanvalue = False;
1b6c52dc 258 else if (buf[0] != 0) {
df52b790 259 done = 0;
260 printf("Please answer True or False\r\n");
261 }
262 }
263 break;
264 case FT_STRING:
265 if (*StringValue(f, i))
266 printf("%s[%s]: ", p->prompt, StringValue(f, i));
267 else
268 printf("%s: ", p->prompt);
269 fflush(stdout);
270 if (mgets(buf, sizeof(buf)))
271 return;
272 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
273 if (strlen(buf) != 0)
274 StoreField(f, i, buf);
275 if (!strcmp(buf, "\"\""))
276 StoreField(f, i, "");
277 break;
278 case FT_KEYWORD:
698271c7 279 k = strchr(p->prompt, '|');
df52b790 280 if (k) *k = 0;
281 done = 0;
282 while (done != 1) {
283 if (*StringValue(f, i))
284 printf("%s[%s]: ", p->prompt, StringValue(f, i));
285 else
286 printf("%s: ", p->prompt);
287 fflush(stdout);
288 if (mgets(buf, sizeof(buf)))
289 return;
290 if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
291 if (strlen(buf) == 0)
292 strcpy(buf, StringValue(f, i));
293 done = 0;
294 for (j = 0; p->keywords[j]; j++)
295 if (!strncasecmp(p->keywords[j], buf, strlen(buf)))
296 done++, best = j;
297 if (done != 1) {
298 printf("You must enter one of these keywords:\r\n");
299 for (j = 0; p->keywords[j]; j++) {
300 printf(" %s\r\n", p->keywords[j]);
301 }
302 } else
303 StoreField(f, i, p->keywords[best]);
304 }
305 break;
306 }
307 }
308 process_form(f, TRUE);
309}
310
311
312int mgets(line, linelen)
313char *line;
314int linelen;
315{
316 char c, *p;
317
318 raw_mode();
319 p = &line[0];
320 *p = 0;
321 for (c = (getchar() & 0x7f); 1; c = (getchar() & 0x7f)) {
322 if (c == 0) continue;
323 switch (c) {
324 case 127:
325 case '\b':
326 if (p == &line[0]) {
327 putchar(7);
328 break;
329 }
330 *(--p) = 0;
331 write(1, "\b \b", 3);
332 break;
333 case 'C' - '@':
334 case 'G' - '@':
335 cooked_mode();
336 return(-1);
337 case 'Q' - '@':
338 case 'V' - '@':
339 putchar('\\');
340 c = getchar();
341 if (c < ' ')
342 printf("\b^%c", c + '@');
343 else
344 printf("\b%c", c);
345 fflush(stdout);
346 *p++ = c;
347 break;
348 case 'W' - '@':
349 if (p > &line[0])
350 p--;
351 while ((p >= &line[0]) && isspace(*p)) {
352 write(1, "\b \b", 3);
353 p--;
354 }
355 while ((p >= &line[0]) && !isspace(*p)) {
356 write(1, "\b \b", 3);
357 p--;
358 }
359 if (p > &line[0]) {
360 p++;
361 } else {
362 p = &line[0];
363 }
364 *p = 0;
365 break;
366 case 'Z' - '@':
367 printf("\r\n");
368 kill(getpid(), SIGSTOP);
369 /* when continued, fall through to */
370 case 'R' - '@':
371 *p = 0;
372 printf("\r\n%s", line);
373 fflush(stdout);
374 break;
375 case 'U' - '@':
376 while (p-- > &line[0])
377 write(1, "\b \b", 3);
378 *(++p) = 0;
379 fflush(stdout);
380 break;
381 case '\n':
382 case '\r':
383 write(1, "\r\n", 2);
384 cooked_mode();
385 return(0);
386 break;
387 default:
388 putchar(c);
389 *p++ = c;
390 *p = 0;
391 }
392 }
393}
394
395
396print_parse_tree(n, l)
397struct parse_node *n;
398int l;
399{
400 int i;
401
402 for (i = l; i > 0; i--) putchar(' ');
403 printf("%s%c\n", n->p_word, n->p_menu ? '*' : ' ');
404 if (n->p_next)
405 print_parse_tree(n->p_next, l+1);
406 if (n->p_peer)
407 return(print_parse_tree(n->p_peer, l));
48a59f6d 408}
This page took 0.123406 seconds and 5 git commands to generate.