]> diplodocus.org Git - nmh/blob - sbr/getansreadline.c
Add support for a -nosasl switch.
[nmh] / sbr / getansreadline.c
1
2 /*
3 * getansreadline.c -- get an answer from the user, with readline
4 *
5 * This code is Copyright (c) 2012, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
8 */
9
10 #include <h/mh.h>
11 #include <h/signals.h>
12 #include <setjmp.h>
13 #include <signal.h>
14 #include <errno.h>
15
16 #ifdef READLINE_SUPPORT
17 #include <readline/readline.h>
18 #include <readline/history.h>
19
20 static struct swit *rl_cmds;
21
22 static char *nmh_command_generator(const char *, int);
23 static char **nmh_completion(const char *, int, int);
24 static void initialize_readline(void);
25
26 static char ansbuf[BUFSIZ];
27 #if 0
28 static sigjmp_buf sigenv;
29
30 /*
31 * static prototypes
32 */
33 static void intrser (int);
34
35
36 char **
37 getans (char *prompt, struct swit *ansp)
38 {
39 int i;
40 SIGNAL_HANDLER istat = NULL;
41 char *cp, **cpp;
42
43 if (!(sigsetjmp(sigenv, 1))) {
44 istat = SIGNAL (SIGINT, intrser);
45 } else {
46 SIGNAL (SIGINT, istat);
47 return NULL;
48 }
49
50 for (;;) {
51 printf ("%s", prompt);
52 fflush (stdout);
53 cp = ansbuf;
54 while ((i = getchar ()) != '\n') {
55 if (i == EOF) {
56 /*
57 * If we get an EOF, return
58 */
59 if (feof(stdin))
60 siglongjmp (sigenv, 1);
61
62 /*
63 * For errors, if we get an EINTR that means that we got
64 * a signal and we should retry. If we get another error,
65 * then just return.
66 */
67
68 else if (ferror(stdin)) {
69 if (errno == EINTR) {
70 clearerr(stdin);
71 continue;
72 }
73 fprintf(stderr, "\nError %s during read\n",
74 strerror(errno));
75 siglongjmp (sigenv, 1);
76 } else {
77 /*
78 * Just for completeness's sake ...
79 */
80
81 fprintf(stderr, "\nUnknown problem in getchar()\n");
82 siglongjmp (sigenv, 1);
83 }
84 }
85 if (cp < &ansbuf[sizeof ansbuf - 1])
86 *cp++ = i;
87 }
88 *cp = '\0';
89 if (ansbuf[0] == '?' || cp == ansbuf) {
90 printf ("Options are:\n");
91 print_sw (ALL, ansp, "", stdout);
92 continue;
93 }
94 cpp = brkstring (ansbuf, " ", NULL);
95 switch (smatch (*cpp, ansp)) {
96 case AMBIGSW:
97 ambigsw (*cpp, ansp);
98 continue;
99 case UNKWNSW:
100 printf (" -%s unknown. Hit <CR> for help.\n", *cpp);
101 continue;
102 default:
103 SIGNAL (SIGINT, istat);
104 return cpp;
105 }
106 }
107 }
108
109
110 static void
111 intrser (int i)
112 {
113 NMH_UNUSED (i);
114
115 /*
116 * should this be siglongjmp?
117 */
118 siglongjmp (sigenv, 1);
119 }
120 #endif
121
122 /*
123 * getans, but with readline support
124 */
125
126 char **
127 getans_via_readline(char *prompt, struct swit *ansp)
128 {
129 char *ans, **cpp;
130
131 initialize_readline();
132 rl_cmds = ansp;
133
134 for (;;) {
135 ans = readline(prompt);
136 /*
137 * If we get an EOF, return
138 */
139
140 if (ans == NULL)
141 return NULL;
142
143 if (ans[0] == '?' || ans[0] == '\0') {
144 printf("Options are:\n");
145 print_sw(ALL, ansp, "", stdout);
146 free(ans);
147 continue;
148 }
149 add_history(ans);
150 strncpy(ansbuf, ans, sizeof(ansbuf));
151 ansbuf[sizeof(ansbuf) - 1] = '\0';
152 cpp = brkstring(ansbuf, " ", NULL);
153 switch (smatch(*cpp, ansp)) {
154 case AMBIGSW:
155 ambigsw(*cpp, ansp);
156 continue;
157 case UNKWNSW:
158 printf(" -%s unknown. Hit <CR> for help.\n", *cpp);
159 continue;
160 default:
161 free(ans);
162 return cpp;
163 }
164 free(ans);
165 }
166 }
167
168 static void
169 initialize_readline(void)
170 {
171 rl_readline_name = "Nmh";
172 rl_attempted_completion_function = nmh_completion;
173 }
174
175 static char **
176 nmh_completion(const char *text, int start, int end)
177 {
178 char **matches;
179
180 NMH_UNUSED (end);
181
182 matches = (char **) NULL;
183
184 if (start == 0)
185 matches = rl_completion_matches(text, nmh_command_generator);
186
187 return matches;
188 }
189
190 static char *
191 nmh_command_generator(const char *text, int state)
192 {
193 static int list_index, len;
194 char *name, *p;
195 char buf[256];
196
197 if (!state) {
198 list_index = 0;
199 len = strlen(text);
200 }
201
202 while ((name = rl_cmds[list_index].sw)) {
203 list_index++;
204 strncpy(buf, name, sizeof(buf));
205 buf[sizeof(buf) - 1] = '\0';
206 p = *brkstring(buf, " ", NULL);
207 if (strncmp(p, text, len) == 0)
208 return strdup(p);
209 }
210
211 return NULL;
212 }
213 #endif /* READLINE_SUPPORT */
214