File: input.c

package info (click to toggle)
ap-utils 1.5-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 2,752 kB
  • sloc: ansic: 22,708; sh: 3,973; yacc: 316; makefile: 310
file content (468 lines) | stat: -rw-r--r-- 11,114 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
/*
 *      input.c from Access Point SNMP Utils for Linux
 *	program input & screen related functions
 *
 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
 * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 from
 * June 1991 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <menu.h>
#include <errno.h>
#include "ap-utils.h"

extern WINDOW *main_sub, *win_for_help;

#define GEN_IV_MSG _("Invalid value. Press any key to continue.")
#define OOR_IV_MSG _("Value must be in range %u - %u. Press any key to continue.")

#define MAC_LEN 12
#define MAC_BYTES 6

void
get_mac(char *mac, int row, int col)
{
    char message[MAC_LEN+1], mess[MAC_LEN/MAC_BYTES+1];
    int i;

    message[0] = '\0';
    while (strlen(message) != 12)
	get_value(message, row, col, MAC_LEN+1, HEX_STRING, 0, 0, NULL);

    for (i = 0; i < MAC_BYTES; i++) {
	mess[0] = message[2 * i];
	mess[1] = message[2 * i + 1];
	mess[2] = '\0';
	mac[i] = strtol(mess, NULL, 16);
    }
}

#define IP_LEN 15

void
get_ip(struct in_addr *ip, int row, int col, char *helpmsg)
{
    char message[IP_LEN+1], *cp;
    int dotc;

get_ip_again:
    get_value(message, row, col, IP_LEN+1, ANY_STRING, 0, 0, NULL);
    for (cp = message, dotc = 0; *cp && (cp = index(cp, '.')); cp++, dotc++);
    if (dotc < 3 || !(inet_aton(message, ip))) {
	if (helpmsg) {
	    print_helperr(GEN_IV_MSG);
	    getch();
	    print_help(helpmsg);
	}
	goto get_ip_again;
    }
}

void
get_mask(struct in_addr *ip, int row, int col, char *helpmsg)
{
    int i, bit, hmask, trans_count;

get_mask_again:
    trans_count = 0;
    get_ip(ip, row, col, helpmsg);
    hmask = ntohl(ip->s_addr);
    bit = hmask & 0x00000001;
    for (i = 1; i < 32; i++)
	if (((hmask >> i) & 0x00000001) != bit) {
	    bit ^= 0x00000001;
	    trans_count++;
	}

    if (trans_count > 1) {
	print_helperr(GEN_IV_MSG);
	getch();
	print_help(helpmsg);
	goto get_mask_again;
    }
}

/*
 * This is the main input function for all cases when user needs to enter
 * a visible string. It also performs syntax correctness checks
 * as well as bounds checks if required.
 *
 * value ....... this should keep the value, entered by the user,
 *		 in ascii string notation
 * row
 * col ......... the begin coordinates, relative to the current window,
 *		 at which the string entered by the user will appear
 * len ......... maximum length of the entered string, including the
 *		 tailing '\0' character. Negative value along with
 *		 vt=ANY_STRING means that zero-length string is allowed.
 * vt .......... desired input value type (types INT_STRING, HEX_STRING,
 *		 ANY_STRING)
 * minv, maxv .. min/max bounds in case of integer value input. Each can be
 *		 of value 0-0xFFFFFFFF. If both are 0, it means no value bounds
 *		 checking will be performed. Used only with vt=INT_STRING.
 * helpmsg ..... pointer to string that will be printed after OOR_IV_MSG
 *		 message if the entered integer value is out of range.
 *		 If NULL, then no 'invalid value' and subsequent status line
 *		 message will be printed, and whole input process will be
 *		 repeated. Used only with vt=INT_STRING.
 */
void
get_value(char *value, int row, int col, int len,
	  char vt, unsigned int minv, unsigned int maxv, char *helpmsg)
{
    int c, i, x, y;
    unsigned char acs;
    char iv_msg[128], zerolen_perm = 0;
    enum { INSERT, OVERWRITE } mode;
    WINDOW *gv_win;

    if (vt == ANY_STRING && len < 0) {
	zerolen_perm = 1;
	len = -len;
    }

    gv_win = derwin(main_sub, 1, len - 1, row, col);
    wbkgdset(gv_win, A_REVERSE);

get_value_again:
    mode = INSERT;
    curs_set(1);
    werase(gv_win);
    wrefresh(gv_win);

    i = 0; /* means 'character count' here */
    while (1) {
	c = getch();
	acs = 0;
	switch (vt) {
	    case INT_STRING:
		if (c >= '0' && c <= '9') acs = 1;
		break;
	    case HEX_STRING:
		if ((c >= '0' && c <= '9') ||
		    (c >= 'a' && c <= 'f') ||
		    (c >= 'A' && c <= 'F')) acs = 1;
		break;
	    case ANY_STRING:
		acs = 1;
	}
	/* rather do not ask, how this works... */
	getyx(gv_win, y, x);
	switch (c) {
	    case KEY_BACKSPACE:
		/* lefthandside DELETE */
		if (x > 0) {
		    /*
		     * do not step cursor back only if window is filled AND
		     * cursor is totally on RHS
		     */
		    if ((i < len - 1) || (x < len - 2))
			x--;
		    mvwdelch(gv_win, 0, x);
		    wrefresh(gv_win);
		    i--;
		}
		break;
	    case KEY_DC:
		/* righthandside DELETE */
		if (i > 0) {
		    if (x == i)
			x--;
		    mvwdelch(gv_win, 0, x);
		    wrefresh(gv_win);
		    i--;
		}
		break;
	    case KEY_LEFT:
		if (x > 0) {
		    wmove(gv_win, 0, --x);
		    wrefresh(gv_win);
		}
		break;
	    case KEY_RIGHT:
		if (x < i) {
		    wmove(gv_win, 0, ++x);
		    wrefresh(gv_win);
		}
		break;
	    case KEY_HOME:
		wmove(gv_win, 0, 0);
		wrefresh(gv_win);
		break;
	    case KEY_END:
		wmove(gv_win, 0, (i == len - 1 ? i - 1 : i));
		wrefresh(gv_win);
		break;
	    case KEY_IC:
		mode = (mode == INSERT ? OVERWRITE : INSERT);
		curs_set(mode == INSERT ? 1 : 2);
		break;
	    case 0x0A:
		/* ENTER KEY */
		if (i > 0 || zerolen_perm)
		    goto away;

		break;
	    default:
		if (acs && (c < 0x100)) {
		    if (mode == INSERT) {
			if (i < len - 1) {
			    winsch(gv_win, c);
			    i++;
			    wmove(gv_win, 0, ++x);
			    wrefresh(gv_win);
			}
		    } else {
			if (i <= len - 1) {
//			    wechochar(gv_win, c);
			    waddch(gv_win, c);
			    if (x == i)
				i++;
			    wmove(gv_win, 0, ++x);
			    wrefresh(gv_win);
			}
		    }
		}
	}
    }

away:
    wmove(gv_win, 0, 0);
    winnstr(gv_win, value, i);
    value[i] = 0;
    curs_set(0);

    if (vt == INT_STRING) {
	i = strtoul(value, (char **)NULL, 10);
	sprintf(value, "%i", i); /* eat leading zeros */
	if (minv | maxv) {
	    errno = 0;
	    if ((unsigned)i < minv || (unsigned)i > maxv || errno == ERANGE) {
		if (helpmsg) {
		    snprintf(iv_msg, sizeof(iv_msg) -1, OOR_IV_MSG, minv, maxv);
		    print_helperr(iv_msg);
		    getch();
		    print_help(helpmsg);
		}
		goto get_value_again;
	    }
	}
    }

    wbkgdset(gv_win, A_BOLD);
    werase(gv_win);
    waddstr(gv_win, value);
    wrefresh(gv_win);
//    mvwprintw(main_sub, 18, 1, "length: %i", i);
//    wrefresh(main_sub);
    delwin(gv_win);
}

/*
 * Note: indeed we should use get_value() for this action, but for the moment,
 * we'll settle with this one.
 */

void
get_pass(char *value, int row, int col, int len)
{
    int i, j = 0;

    wattrset(main_sub, COLOR_PAIR(12));
    wmove(main_sub, row, col);
    for (i = 0; i < len - 1; i++)
	waddch(main_sub, ' ');
    curs_set(1);

    while (1) {
	value[j] = mvwgetch(main_sub, row, col + j);
	if (value[j] == 0x0A) /* NEWLINE */
	    break;
	if (value[j] == 0x1B) /* ESCAPE */
	    continue;
	if (value[j] != 0x7F) { /* BACKSPACE */
	    if (j < len - 1)
		mvwaddch(main_sub, row, col + j++, '*');
	} else {
	    if (j)
		mvwaddch(main_sub, row, col + --j, ' ');
	}
    };
    value[j] = '\0';

    curs_set(0);
    wattrset(main_sub, A_BOLD);
    wmove(main_sub, row, col);
    for (i = 0; i < len - 1; i++)
	waddch(main_sub, ' ');
    wmove(main_sub, row, col);
    for (i = 0; i < j; i++)
	waddch(main_sub, '*');
    wattrset(main_sub, A_NORMAL);
    wrefresh(main_sub);
}

int
yes_no(int brow, int bcol)
{
    char *names[2] = { YES, NO };

    return menu_choose(brow, bcol, names, 2) + 1;
}

int
on_off(int brow, int bcol)
{
    char *names[2] = { ON, OFF };

    return menu_choose(brow, bcol, names, 2) + 1;
}

int menu_choose(int brow, int bcol, char **names, unsigned int num)
{
    unsigned short int c;
    ITEM **menu_item = calloc(num, sizeof(ITEM)), **ip = menu_item;
    MENU *menu1;
    unsigned int ncol = 2, i, nrow;
    WINDOW *choose_menu, *sub_choose_menu;
    extern WINDOW *main_sub;

    for (i = 0; i < num; i++) {
	*ip++ = new_item(names[i], "");
	if (ncol < strlen(names[i]) + 3)
	    ncol = strlen(names[i]) + 3;
    }
    *ip = (ITEM *) 0;


    nrow = num + 2;
    if (brow + 2 + nrow <= (unsigned int) LINES - 2)
	choose_menu = newwin(nrow, ncol, brow + 2, bcol + MCOLS);
    else
	choose_menu = newwin(nrow, ncol, brow - nrow + 3, bcol + MCOLS);
    sub_choose_menu = derwin(choose_menu, nrow - 2, ncol - 2, 1, 1);
    attrset(COLOR_PAIR(11));

    mvwaddch(choose_menu, 0, 0, ACS_ULCORNER);
    mvwaddch(choose_menu, 0, ncol - 1, ACS_URCORNER);
    mvwaddch(choose_menu, nrow - 1, 0, ACS_LLCORNER);
    mvwaddch(choose_menu, nrow - 1, ncol - 1, ACS_LRCORNER);
    for (i = 1; i < ncol - 1; i++) {
	mvwaddch(choose_menu, 0, i, ACS_HLINE);
	mvwaddch(choose_menu, nrow - 1, i, ACS_HLINE);
    }
    for (i = 1; i < nrow - 1; i++) {
	mvwaddch(choose_menu, i, 0, ACS_VLINE);
	mvwaddch(choose_menu, i, ncol - 1, ACS_VLINE);
    }
    wrefresh(choose_menu);


    menu1 = new_menu(menu_item);
    set_menu_win(menu1, choose_menu);
    set_menu_sub(menu1, sub_choose_menu);

    set_menu_opts(menu1, O_ONEVALUE);

    curs_set(0);
    post_menu(menu1);
    wrefresh(sub_choose_menu);

    while (1) {
	switch (getch()) {
	case KEY_DOWN:
	case 'j':
	case 'J':
	    menu_driver(menu1, REQ_NEXT_ITEM);
	    wrefresh(sub_choose_menu);
	    break;
	case KEY_RIGHT:
	case 'l':
	case 'L':
	    menu_driver(menu1, REQ_LAST_ITEM);
	    wrefresh(sub_choose_menu);
	    break;
	case KEY_LEFT:
	case 'h':
	case 'H':
	    menu_driver(menu1, REQ_FIRST_ITEM);
	    wrefresh(sub_choose_menu);
	    break;
	case KEY_UP:
	case 'k':
	case 'K':
	    menu_driver(menu1, REQ_PREV_ITEM);
	    wrefresh(sub_choose_menu);
	    break;
	case 10:
	    i = item_index(current_item(menu1));
	    unpost_menu(menu1);
	    free_menu(menu1);
	    for (c = 0; c < nrow - 2; c++)
		free_item(menu_item[c]);
	    delwin(sub_choose_menu);
	    delwin(choose_menu);
	    redrawwin(main_sub);
	    free(menu_item);
	    return i;

	}
    }
}

/*
 * Reads key by either no-delay getch() (WAIT_FOREVER mode) or using
 * getch() with tval tenths of second timeout (WAIT_TIMEOUT mode).
 * Returns 0 for timeout, or pressed key code.
 */
int wait_key(int tval)
{
    int i;
    extern int wait_mode;

    if (wait_mode == WAIT_TIMEOUT)
	timeout(tval * 100);

    i = getch();

    if (wait_mode == WAIT_TIMEOUT) {
	timeout(-1);
//	nocbreak();
//	cbreak();
    }

    if (i == ERR)
	i = 0;

    return i;
}

int help_ysn()
{
    char c;

    print_help (_("Y - Yes; Any other key - No (it's safer to answer No)"));
    c = getch();
    clear_main(0);
    if (c == 'y' || c == 'Y')
	return 0;

    return 1;
}