]> git.decadent.org.uk Git - ap-utils.git/blob - lib/input.c
2e918ee83cf33b8324a0d0c64b6eabe079bcc89f
[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 <unistd.h>
25 #include <menu.h>
26 #include "ap-utils.h"
27 #include "ap-curses.h"
28
29 extern WINDOW *main_sub, *win_for_help, *main_win;
30
31 #define GEN_IV_MSG _("Invalid value. Press any key to continue.")
32 #define OOR_IV_MSG _("Value must be in range %i - %i. Press any key to continue.")
33
34 #define MAC_LEN 12
35 #define MAC_BYTES 6
36
37 void
38 get_mac(char *mac, int row, int col)
39 {
40     char message[MAC_LEN+1], mess[MAC_LEN/MAC_BYTES+1];
41     int i;
42
43     get_value(message, row, col, MAC_LEN+1, HEX_STRING, 0, 0, NULL);
44     if (strlen(message) < 12) i = 255;
45
46     for (i = 0; i < MAC_BYTES; i++) {
47         mess[0] = message[2 * i];
48         mess[1] = message[2 * i + 1];
49         mess[2] = '\0';
50         mac[i] = strtol(mess, NULL, 16);
51     }
52 }
53
54 #define IP_LEN 15
55
56 void
57 get_ip(struct in_addr *ip, int row, int col, char *helpmsg)
58 {
59     char message[IP_LEN+1], *cp;
60     int dotc;
61
62 get_ip_again:
63     get_value(message, row, col, IP_LEN+1, ANY_STRING, 0, 0, NULL);
64     for (cp = message, dotc = 0; *cp && (cp = index(cp, '.')); cp++, dotc++);
65     if (dotc < 3 || !(inet_aton(message, ip))) {
66         if (helpmsg) {
67             print_helperr(GEN_IV_MSG);
68             getch();
69             print_help(helpmsg);
70         }
71         goto get_ip_again;
72     }
73 }
74
75 void
76 get_mask(struct in_addr *ip, int row, int col, char *helpmsg)
77 {
78     int i, bit, hmask, trans_count = 0;
79
80 get_mask_again:
81     get_ip(ip, row, col, helpmsg);
82     hmask = ntohl(ip->s_addr);
83     bit = hmask & 0x00000001;
84     for (i = 1; i < 32; i++)
85         if (((hmask >> i) & 0x00000001) != bit) {
86             bit ^= 0x00000001;
87             trans_count++;
88         }
89
90     if (trans_count > 1) {
91         print_helperr(GEN_IV_MSG);
92         getch();
93         print_help(helpmsg);
94         goto get_mask_again;
95     }
96 }
97
98 /*
99  * This is the main input function for all cases when user needs to enter
100  * a visible string. It also performs syntax correctness checks
101  * as well as bounds checks if required.
102  *
103  * value ....... this should keep the value, entered by the user,
104  *               in ascii string notation
105  * row
106  * col ......... the begin coordinate, relative to the current window,
107  *               at which the string entered by the user will appear
108  * len ......... maximum length of the entered string, including the
109  *               tailing '\0' character
110  * vt .......... desired input value type (types INT_STRING, HEX_STRING,
111  *               ANY_STRING)
112  * minv, maxv .. min/max bounds in case of integer value input. Each can be
113  *               of value 0 - maxint. If both are 0, it means no value bounds
114  *               checking will be performed. Used only with vt=INT_STRING.
115  * helpmsg ..... pointer to string that will be printed after OOR_IV_MSG
116  *               message if the entered integer value is out of range.
117  *               If NULL, then no 'invalid value' and subsequent status line
118  *               message will be printed, and whole input process will be
119  *               repeated. Used only with vt=INT_STRING.
120  */
121 void
122 get_value(char *value, int row, int col, int len,
123           char vt, int minv, int maxv, char *helpmsg)
124 {
125     int i;
126     unsigned char c, acs;
127     char iv_msg[128];
128
129     echo();
130     wattrset(main_sub, COLOR_PAIR(2));
131 get_value_again:
132     wmove(main_sub, row, col);
133     for (i = 0; i < len - 1; i++)
134         waddch(main_sub, ' ');
135     curs_set(1);
136     wmove(main_sub, row, col);
137     wrefresh(main_sub);
138
139     i = 0;
140     while (1) {
141         c = getchar();
142         acs = 0;
143         switch (vt) {
144             case INT_STRING:
145                 if (c >= '0' && c <= '9') acs = 1;
146                 break;
147             case HEX_STRING:
148                 if ((c >= '0' && c <= '9') ||
149                     (c >= 'a' && c <= 'f') ||
150                     (c >= 'A' && c <= 'F')) acs = 1;
151                 break;
152             case ANY_STRING:
153                 acs = 1;
154         }
155         if (c == 0x7F) {
156             /* DELETE KEY */
157             if (i > 0) {
158                 value[i--] = 0;
159                 wmove(main_sub, row, col + i);
160                 waddch(main_sub, ' ');
161                 /* put backspace to move cursor back */
162                 wechochar(main_sub, 0x08);
163             }
164             continue;
165         } else if (c == 0x0D) {
166             /* ENTER KEY */
167             if (i > 0)
168                 break;
169             continue;
170         } else if (c == 0x1B) {
171             /* ESCAPE KEY */
172             continue;
173         } else if (acs && (i < len - 1)) {
174             value[i++] = c;
175             wechochar(main_sub, c);
176         }
177     }
178     value[i] = 0;
179
180     noecho();
181     if (vt == INT_STRING && (minv | maxv)) {
182         i = atoi(value);
183         if (i < minv || i > maxv) {
184             if (helpmsg) {
185                 snprintf(iv_msg, sizeof(iv_msg) - 1, OOR_IV_MSG, minv, maxv);
186                 print_helperr(iv_msg);
187                 getch();
188                 print_help(helpmsg);
189             }
190             goto get_value_again;
191         }
192     }
193
194     curs_set(0);
195     wattrset(main_sub, A_BOLD);
196     wmove(main_sub, row, col);
197     for (i = 0; i < len - 1; i++)
198         waddch(main_sub, ' ');
199     mvwaddstr(main_sub, row, col, value);
200     wattrset(main_sub, A_NORMAL);
201     wrefresh(main_sub);
202 }
203
204 /*
205  * Note: indeed we should use get_value() for this action, but for the moment,
206  * we'll settle with this one.
207  */
208
209 void
210 get_pass(char *value, int row, int col, int len)
211 {
212     int i, j = 0;
213
214     wattrset(main_sub, COLOR_PAIR(2));
215     wmove(main_sub, row, col);
216     for (i = 0; i < len - 1; i++)
217         waddch(main_sub, ' ');
218     curs_set(1);
219
220     while (1) {
221         value[j] = mvwgetch(main_sub, row, col + j);
222         if (value[j] == 0x0A) /* NEWLINE */
223             break;
224         if (value[j] == 0x1B) /* ESCAPE */
225             continue;
226         if (value[j] != 0x7F) { /* BACKSPACE */
227             if (j < len - 1)
228                 mvwaddch(main_sub, row, col + j++, '*');
229         } else {
230             if (j)
231                 mvwaddch(main_sub, row, col + --j, ' ');
232         }
233     };
234     value[j] = '\0';
235
236     curs_set(0);
237     wattrset(main_sub, A_BOLD);
238     wmove(main_sub, row, col);
239     for (i = 0; i < len - 1; i++)
240         waddch(main_sub, ' ');
241     wmove(main_sub, row, col);
242     for (i = 0; i < j; i++)
243         waddch(main_sub, '*');
244     wattrset(main_sub, A_NORMAL);
245     wrefresh(main_sub);
246 }
247
248 int
249 yes_no(int brow, int bcol)
250 {
251     char *names[2] = { YES, NO };
252
253     return menu_choose(brow, bcol, names, 2) + 1;
254 }
255
256 int
257 on_off(int brow, int bcol)
258 {
259     char *names[2] = { ON, OFF };
260
261     return menu_choose(brow, bcol, names, 2) + 1;
262 }
263
264 int menu_choose(int brow, int bcol, char **names, unsigned int num)
265 {
266     unsigned short int c;
267     ITEM **menu_item = calloc(num, sizeof(ITEM)), **ip = menu_item;
268     MENU *menu1;
269     unsigned int ncol = 2, i, nrow;
270     WINDOW *choose_menu, *sub_choose_menu;
271     extern WINDOW *main_sub;
272
273     for (i = 0; i < num; i++) {
274         *ip++ = new_item(names[i], "");
275         if (ncol < strlen(names[i]) + 3)
276             ncol = strlen(names[i]) + 3;
277     }
278     *ip = (ITEM *) 0;
279
280
281     nrow = num + 2;
282     if (brow + 2 + nrow <= (unsigned int) LINES - 2)
283         choose_menu = newwin(nrow, ncol, brow + 2, bcol + MCOLS);
284     else
285         choose_menu = newwin(nrow, ncol, brow - nrow + 3, bcol + MCOLS);
286     sub_choose_menu = derwin(choose_menu, nrow - 2, ncol - 2, 1, 1);
287     attrset(COLOR_PAIR(1));
288
289     mvwaddch(choose_menu, 0, 0, ACS_ULCORNER);
290     mvwaddch(choose_menu, 0, ncol - 1, ACS_URCORNER);
291     mvwaddch(choose_menu, nrow - 1, 0, ACS_LLCORNER);
292     mvwaddch(choose_menu, nrow - 1, ncol - 1, ACS_LRCORNER);
293     for (i = 1; i < ncol - 1; i++) {
294         mvwaddch(choose_menu, 0, i, ACS_HLINE);
295         mvwaddch(choose_menu, nrow - 1, i, ACS_HLINE);
296     }
297     for (i = 1; i < nrow - 1; i++) {
298         mvwaddch(choose_menu, i, 0, ACS_VLINE);
299         mvwaddch(choose_menu, i, ncol - 1, ACS_VLINE);
300     }
301     wrefresh(choose_menu);
302
303
304     menu1 = new_menu(menu_item);
305     set_menu_win(menu1, choose_menu);
306     set_menu_sub(menu1, sub_choose_menu);
307
308     set_menu_opts(menu1, O_ONEVALUE);
309
310     curs_set(0);
311     post_menu(menu1);
312     wrefresh(sub_choose_menu);
313
314     while (1) {
315         switch (getch()) {
316         case KEY_DOWN:
317         case 'j':
318         case 'J':
319             menu_driver(menu1, REQ_NEXT_ITEM);
320             wrefresh(sub_choose_menu);
321             break;
322         case KEY_RIGHT:
323         case 'l':
324         case 'L':
325             menu_driver(menu1, REQ_LAST_ITEM);
326             wrefresh(sub_choose_menu);
327             break;
328         case KEY_LEFT:
329         case 'h':
330         case 'H':
331             menu_driver(menu1, REQ_FIRST_ITEM);
332             wrefresh(sub_choose_menu);
333             break;
334         case KEY_UP:
335         case 'k':
336         case 'K':
337             menu_driver(menu1, REQ_PREV_ITEM);
338             wrefresh(sub_choose_menu);
339             break;
340         case 10:
341             i = item_index(current_item(menu1));
342             unpost_menu(menu1);
343             free_menu(menu1);
344             for (c = 0; c < nrow - 2; c++)
345                 free_item(menu_item[c]);
346             delwin(sub_choose_menu);
347             delwin(choose_menu);
348             redrawwin(main_sub);
349             free(menu_item);
350             return i;
351
352         }
353     }
354 }
355