]> git.decadent.org.uk Git - ap-utils.git/blob - lib/input.c
Imported Upstream version 1.5~pre3~a
[ap-utils.git] / lib / input.c
1 /*
2  *      scr.c from Access Point SNMP Utils for Linux
3  *      program input & screen related functions
4  *
5  * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License Version 2 from
9  * June 1991 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <menu.h>
28 #include <errno.h>
29 #include "ap-utils.h"
30
31 extern WINDOW *main_sub, *win_for_help;
32
33 #define GEN_IV_MSG _("Invalid value. Press any key to continue.")
34 #define OOR_IV_MSG _("Value must be in range %u - %u. Press any key to continue.")
35
36 #define MAC_LEN 12
37 #define MAC_BYTES 6
38
39 void
40 get_mac(char *mac, int row, int col)
41 {
42     char message[MAC_LEN+1], mess[MAC_LEN/MAC_BYTES+1];
43     int i;
44
45     message[0] = '\0';
46     while (strlen(message) != 12)
47         get_value(message, row, col, MAC_LEN+1, HEX_STRING, 0, 0, NULL);
48
49     for (i = 0; i < MAC_BYTES; i++) {
50         mess[0] = message[2 * i];
51         mess[1] = message[2 * i + 1];
52         mess[2] = '\0';
53         mac[i] = strtol(mess, NULL, 16);
54     }
55 }
56
57 #define IP_LEN 15
58
59 void
60 get_ip(struct in_addr *ip, int row, int col, char *helpmsg)
61 {
62     char message[IP_LEN+1], *cp;
63     int dotc;
64
65 get_ip_again:
66     get_value(message, row, col, IP_LEN+1, ANY_STRING, 0, 0, NULL);
67     for (cp = message, dotc = 0; *cp && (cp = index(cp, '.')); cp++, dotc++);
68     if (dotc < 3 || !(inet_aton(message, ip))) {
69         if (helpmsg) {
70             print_helperr(GEN_IV_MSG);
71             getch();
72             print_help(helpmsg);
73         }
74         goto get_ip_again;
75     }
76 }
77
78 void
79 get_mask(struct in_addr *ip, int row, int col, char *helpmsg)
80 {
81     int i, bit, hmask, trans_count = 0;
82
83 get_mask_again:
84     get_ip(ip, row, col, helpmsg);
85     hmask = ntohl(ip->s_addr);
86     bit = hmask & 0x00000001;
87     for (i = 1; i < 32; i++)
88         if (((hmask >> i) & 0x00000001) != bit) {
89             bit ^= 0x00000001;
90             trans_count++;
91         }
92
93     if (trans_count > 1) {
94         print_helperr(GEN_IV_MSG);
95         getch();
96         print_help(helpmsg);
97         goto get_mask_again;
98     }
99 }
100
101 /*
102  * This is the main input function for all cases when user needs to enter
103  * a visible string. It also performs syntax correctness checks
104  * as well as bounds checks if required.
105  *
106  * value ....... this should keep the value, entered by the user,
107  *               in ascii string notation
108  * row
109  * col ......... the begin coordinates, relative to the current window,
110  *               at which the string entered by the user will appear
111  * len ......... maximum length of the entered string, including the
112  *               tailing '\0' character. Negative value along with
113  *               vt=ANY_STRING means that zero-length string is allowed.
114  * vt .......... desired input value type (types INT_STRING, HEX_STRING,
115  *               ANY_STRING)
116  * minv, maxv .. min/max bounds in case of integer value input. Each can be
117  *               of value 0-0xFFFFFFFF. If both are 0, it means no value bounds
118  *               checking will be performed. Used only with vt=INT_STRING.
119  * helpmsg ..... pointer to string that will be printed after OOR_IV_MSG
120  *               message if the entered integer value is out of range.
121  *               If NULL, then no 'invalid value' and subsequent status line
122  *               message will be printed, and whole input process will be
123  *               repeated. Used only with vt=INT_STRING.
124  */
125 void
126 get_value(char *value, int row, int col, int len,
127           char vt, unsigned int minv, unsigned int maxv, char *helpmsg)
128 {
129     unsigned int i;
130     unsigned char c, acs;
131     char iv_msg[128], zerolen_perm = 0;
132
133     if (vt == ANY_STRING && len < 0) {
134         zerolen_perm = 1;
135         len = -len;
136     }
137
138     echo();
139     wattrset(main_sub, COLOR_PAIR(12));
140 get_value_again:
141     wmove(main_sub, row, col);
142     for (i = 0; i < (unsigned int)len - 1; i++)
143         waddch(main_sub, ' ');
144     curs_set(1);
145     wmove(main_sub, row, col);
146     wrefresh(main_sub);
147
148     i = 0;
149     while (1) {
150         c = getchar();
151         acs = 0;
152         switch (vt) {
153             case INT_STRING:
154                 if (c >= '0' && c <= '9') acs = 1;
155                 break;
156             case HEX_STRING:
157                 if ((c >= '0' && c <= '9') ||
158                     (c >= 'a' && c <= 'f') ||
159                     (c >= 'A' && c <= 'F')) acs = 1;
160                 break;
161             case ANY_STRING:
162                 acs = 1;
163         }
164         if (c == 0x7F) {
165             /* DELETE KEY */
166             if (i > 0) {
167                 value[i--] = 0;
168                 wmove(main_sub, row, col + i);
169                 waddch(main_sub, ' ');
170                 wmove(main_sub, row, col + i);
171                 wrefresh(main_sub);
172             }
173             continue;
174         } else if (c == 0x0D) {
175             /* ENTER KEY */
176             if (i > 0 || zerolen_perm)
177                 break;
178             continue;
179         } else if (c == 0x1B) {
180             /* ESCAPE KEY */
181             continue;
182         } else if (acs && (i < (unsigned int)len - 1)) {
183             value[i++] = c;
184             wechochar(main_sub, c);
185         }
186     }
187     value[i] = 0;
188
189     noecho();
190     if (vt == INT_STRING && (minv | maxv)) {
191         errno = 0;
192         i = strtoul(value, (char **)NULL, 10);
193         if (i < minv || i > maxv || errno == ERANGE) {
194             if (helpmsg) {
195                 snprintf(iv_msg, sizeof(iv_msg) - 1, OOR_IV_MSG, minv, maxv);
196                 print_helperr(iv_msg);
197                 getch();
198                 print_help(helpmsg);
199             }
200             goto get_value_again;
201         }
202     }
203
204     curs_set(0);
205     wattrset(main_sub, A_BOLD);
206     wmove(main_sub, row, col);
207     for (i = 0; i < (unsigned int)len - 1; i++)
208         waddch(main_sub, ' ');
209     mvwaddstr(main_sub, row, col, value);
210     wattrset(main_sub, A_NORMAL);
211     wrefresh(main_sub);
212 }
213
214 /*
215  * Note: indeed we should use get_value() for this action, but for the moment,
216  * we'll settle with this one.
217  */
218
219 void
220 get_pass(char *value, int row, int col, int len)
221 {
222     int i, j = 0;
223
224     wattrset(main_sub, COLOR_PAIR(12));
225     wmove(main_sub, row, col);
226     for (i = 0; i < len - 1; i++)
227         waddch(main_sub, ' ');
228     curs_set(1);
229
230     while (1) {
231         value[j] = mvwgetch(main_sub, row, col + j);
232         if (value[j] == 0x0A) /* NEWLINE */
233             break;
234         if (value[j] == 0x1B) /* ESCAPE */
235             continue;
236         if (value[j] != 0x7F) { /* BACKSPACE */
237             if (j < len - 1)
238                 mvwaddch(main_sub, row, col + j++, '*');
239         } else {
240             if (j)
241                 mvwaddch(main_sub, row, col + --j, ' ');
242         }
243     };
244     value[j] = '\0';
245
246     curs_set(0);
247     wattrset(main_sub, A_BOLD);
248     wmove(main_sub, row, col);
249     for (i = 0; i < len - 1; i++)
250         waddch(main_sub, ' ');
251     wmove(main_sub, row, col);
252     for (i = 0; i < j; i++)
253         waddch(main_sub, '*');
254     wattrset(main_sub, A_NORMAL);
255     wrefresh(main_sub);
256 }
257
258 int
259 yes_no(int brow, int bcol)
260 {
261     char *names[2] = { YES, NO };
262
263     return menu_choose(brow, bcol, names, 2) + 1;
264 }
265
266 int
267 on_off(int brow, int bcol)
268 {
269     char *names[2] = { ON, OFF };
270
271     return menu_choose(brow, bcol, names, 2) + 1;
272 }
273
274 int menu_choose(int brow, int bcol, char **names, unsigned int num)
275 {
276     unsigned short int c;
277     ITEM **menu_item = calloc(num, sizeof(ITEM)), **ip = menu_item;
278     MENU *menu1;
279     unsigned int ncol = 2, i, nrow;
280     WINDOW *choose_menu, *sub_choose_menu;
281     extern WINDOW *main_sub;
282
283     for (i = 0; i < num; i++) {
284         *ip++ = new_item(names[i], "");
285         if (ncol < strlen(names[i]) + 3)
286             ncol = strlen(names[i]) + 3;
287     }
288     *ip = (ITEM *) 0;
289
290
291     nrow = num + 2;
292     if (brow + 2 + nrow <= (unsigned int) LINES - 2)
293         choose_menu = newwin(nrow, ncol, brow + 2, bcol + MCOLS);
294     else
295         choose_menu = newwin(nrow, ncol, brow - nrow + 3, bcol + MCOLS);
296     sub_choose_menu = derwin(choose_menu, nrow - 2, ncol - 2, 1, 1);
297     attrset(COLOR_PAIR(11));
298
299     mvwaddch(choose_menu, 0, 0, ACS_ULCORNER);
300     mvwaddch(choose_menu, 0, ncol - 1, ACS_URCORNER);
301     mvwaddch(choose_menu, nrow - 1, 0, ACS_LLCORNER);
302     mvwaddch(choose_menu, nrow - 1, ncol - 1, ACS_LRCORNER);
303     for (i = 1; i < ncol - 1; i++) {
304         mvwaddch(choose_menu, 0, i, ACS_HLINE);
305         mvwaddch(choose_menu, nrow - 1, i, ACS_HLINE);
306     }
307     for (i = 1; i < nrow - 1; i++) {
308         mvwaddch(choose_menu, i, 0, ACS_VLINE);
309         mvwaddch(choose_menu, i, ncol - 1, ACS_VLINE);
310     }
311     wrefresh(choose_menu);
312
313
314     menu1 = new_menu(menu_item);
315     set_menu_win(menu1, choose_menu);
316     set_menu_sub(menu1, sub_choose_menu);
317
318     set_menu_opts(menu1, O_ONEVALUE);
319
320     curs_set(0);
321     post_menu(menu1);
322     wrefresh(sub_choose_menu);
323
324     while (1) {
325         switch (getch()) {
326         case KEY_DOWN:
327         case 'j':
328         case 'J':
329             menu_driver(menu1, REQ_NEXT_ITEM);
330             wrefresh(sub_choose_menu);
331             break;
332         case KEY_RIGHT:
333         case 'l':
334         case 'L':
335             menu_driver(menu1, REQ_LAST_ITEM);
336             wrefresh(sub_choose_menu);
337             break;
338         case KEY_LEFT:
339         case 'h':
340         case 'H':
341             menu_driver(menu1, REQ_FIRST_ITEM);
342             wrefresh(sub_choose_menu);
343             break;
344         case KEY_UP:
345         case 'k':
346         case 'K':
347             menu_driver(menu1, REQ_PREV_ITEM);
348             wrefresh(sub_choose_menu);
349             break;
350         case 10:
351             i = item_index(current_item(menu1));
352             unpost_menu(menu1);
353             free_menu(menu1);
354             for (c = 0; c < nrow - 2; c++)
355                 free_item(menu_item[c]);
356             delwin(sub_choose_menu);
357             delwin(choose_menu);
358             redrawwin(main_sub);
359             free(menu_item);
360             return i;
361
362         }
363     }
364 }
365
366 /*
367  * Reads key by either getch() (WAIT_FOREVER mode) or select()
368  * (WAIT_TIMEOUT mode). Returns -1 upon error, 0 for timeout, or
369  * pressed key code.
370  */
371 int wait_key()
372 {
373     int i = 0;
374     fd_set rds;
375     struct timeval timeout;
376     extern int wait_mode;
377
378     timeout.tv_sec = 1;
379     timeout.tv_usec = 0;
380     FD_ZERO(&rds);
381     FD_SET(0, &rds);
382
383     if (wait_mode == WAIT_TIMEOUT) {
384         /*
385          * wait up to timeout until anything is avail. for reading
386          * on stdin
387          */
388         i = select(1, &rds, NULL, NULL, &timeout);
389
390         /* not timed out => anything avail. for reading in rds */
391         if (i > 0)
392             i = getc(stdin);
393
394         /* error occured */
395         if (i == -1) {
396             print_helperr(ERR_SELECT);
397             getch();
398         }
399
400         /* also happens: i = 0 => timeout => release */
401
402     } else { /* wait_mode = WAIT_FOREVER */
403         i = getch();
404     }
405
406     return i;
407 }
408
409 int help_ysn()
410 {
411     char c;
412
413     print_help (_("Y - Yes; Any other key - No (it's safer to answer No)"));
414     c = getch();
415     clear_main(0);
416     if (c == 'y' || c == 'Y')
417         return 0;
418
419     return 1;
420 }
421