]> andersk Git - moira.git/blob - clients/mmoira/tty.c
Warn user before letting them rename a list to someone's username.
[moira.git] / clients / mmoira / tty.c
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>
11 #include        <string.h>
12 #include        <sys/types.h>
13 #include        <sys/signal.h>
14 #ifdef POSIX
15 #include        <termios.h>
16 #else
17 #include        <sgtty.h>
18 #endif
19 #include        <sys/ioctl.h>
20 #include        <ctype.h>
21 #include        <X11/Intrinsic.h>
22 #include        <moira.h>
23 #include        "mmoira.h"
24 #include        "parser.h"
25
26 static char rcsid[] = "$Header$";
27
28
29 struct parse_node *TtyCommands = NULL, *TtyRoot = NULL;
30
31 extern int NumMenus;
32 extern MenuItem MenuRoot;
33 char prompt[] = "moira> ";
34
35 #ifdef POSIX
36 static struct termios otty, ntty;
37 #else
38 static struct sgttyb otty, ntty;
39 #endif
40
41 TtyMainLoop()
42 {
43     char buf[1024], cbuf[2], c, *p;
44     int arg, i, done;
45
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 */
54
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
62     ioctl(0, TIOCFLUSH, &arg);
63     ioctl(0, TIOCGETP, &otty);
64     ntty = otty;
65     ntty.sg_flags |= RAW;
66     ntty.sg_flags &= ~ECHO;
67 #endif
68     raw_mode();
69
70     while (1) {
71         parser(prompt, TtyRoot);
72     }
73 }
74
75 cooked_mode()
76 {
77 #ifdef POSIX
78     tcsetattr (0, TCSANOW, &otty);
79 #else
80     ioctl(0, TIOCSETP, &otty);
81 #endif
82 }
83
84 raw_mode()
85 {
86 #ifdef POSIX
87     tcsetattr (0, TCSANOW, &ntty);
88 #else
89     ioctl(0, TIOCSETP, &ntty);
90 #endif
91 }
92
93 static NumWords(s)
94 char *s;
95 {
96     int ret;
97
98     for (ret = 1; *s; s++)
99       if (*s == ' ') ret++;
100     return(ret);
101 }
102
103
104 parse_menus()
105 {
106     int arg;
107     struct parse_node *p;
108
109     TtyCommands = (struct parse_node *)malloc(sizeof(struct parse_node) *
110                                               NumMenus * 3);
111     memset(TtyCommands, 0, sizeof(struct parse_node) * NumMenus * 3);
112     arg = 0;
113     parse_menu_recursive(&MenuRoot, "", &arg);
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++;
122 }
123
124
125 parse_menu_recursive(m, parent, i)
126 MenuItem *m;
127 char *parent;
128 int *i;
129 {
130     char buf[64], cmd[64], *word, *s;
131     struct parse_node *p, **prev;
132     int j, len;
133
134     if (m->submenu == NULL) {
135         if (!strcmp(parent, "file") ||
136             !strcmp(parent, "misc"))
137           parent = "";
138         if (NumWords(m->label) > 2 || !*parent)
139           strcpy(cmd, m->label);
140         else
141           sprintf(cmd, "%s %s", m->label, parent);
142         /* insert command into parse tree */
143         p = TtyRoot;
144         prev = (struct parse_node **) &TtyRoot;
145         for (word = cmd; word; word = strchr(word, ' ')) {
146             if (*word == ' ')
147               word++;
148             s = strchr(word, ' ');
149             if (s)
150               len = s - word;
151             else
152               len = strlen(word);
153             for (;;) {
154                 if (!p || !p->p_word ||
155                     (j = strncmp(p->p_word, word, len)) > 0) {
156                     strcpy(buf, word);
157                     buf[len] = 0;
158 #ifdef DEBUG
159                     printf("word: %s\n", buf);
160 #endif
161                     TtyCommands[*i].p_word = strsave(buf);
162                     if (len == strlen(word))
163                       TtyCommands[*i].p_menu = m;
164                     TtyCommands[*i].p_peer = p;
165                     if (prev)
166                       *prev = &TtyCommands[*i];
167                     TtyCommands[*i].p_next = (struct parse_node *) NULL;
168                     TtyCommands[*i].p_link = (struct parse_node *) NULL;
169                     prev = &(TtyCommands[*i].p_next);
170                     p = (struct parse_node *) NULL;
171                     *i = *i + 1;
172                     break;
173                 } else if (j == 0) {
174                     prev = &(p->p_next);
175                     if (p->p_next)
176                       p = p->p_next;
177                     else
178                       p = (struct parse_node *) NULL;
179                     break;
180                 } else {
181                     prev = &(p->p_peer);
182                     p = p->p_peer;
183                 }
184             }
185         }
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
201 TtyForm(f)
202 EntryForm *f;
203 {
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;
248                 printf("%s(T/F) [%c]: ", p->prompt, boolval(f, i) ? 'T' : 'F');
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;
258                 else if (buf[0] != 0) {
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:
279             k = strchr(p->prompt, '|');
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
312 int mgets(line, linelen)
313 char *line;
314 int 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
396 print_parse_tree(n, l)
397 struct parse_node *n;
398 int 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));
408 }
This page took 0.158728 seconds and 5 git commands to generate.