aboutsummaryrefslogtreecommitdiffstats
path: root/about_scr.c
blob: 31ac37b6011ab8d77f770b213e06029c85b5b533 (plain)
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
/*
 * wavemon - a wireless network monitoring aplication
 *
 * Copyright (c) 2001-2002 Jan Morgenstern <jan@jm-music.de>
 *
 * wavemon is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2, or (at your option) any later
 * version.
 *
 * wavemon 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 wavemon; see the file COPYING.  If not, write to the Free Software
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include "wavemon.h"

/* GLOBALS */
static WINDOW *w_about;

static char *about_lines[] = {
	"wavemon - status monitor for wireless network devices",
	"version " PACKAGE_VERSION " (built " BUILD_DATE ")",
	"",
	"original by jan morgenstern <jan@jm-music.de>",
	"distributed under the GNU general public license v3",
	"",
	"wavemon uses the wireless extensions by",
	"jean tourrilhes <jt@hpl.hp.com>",
	"",
	"please send suggestions and bug reports to ",
	PACKAGE_BUGREPORT,
	"",
	PACKAGE_URL
};

static int *linecd[ARRAY_SIZE(about_lines)], i, j;

void scr_about_init(void)
{
	w_about = newwin_title(0, WAV_HEIGHT, "About", false);

	for (i = 0; i < ARRAY_SIZE(about_lines); i++) {
		linecd[i] = malloc(strlen(about_lines[i]) * sizeof(int));
		for (j = 0; j < strlen(about_lines[i]); j++)
			linecd[i][j] = (rand() / (float)RAND_MAX) * 120 + 60;
	}
}

int scr_about_loop(WINDOW *w_menu)
{
	char buf[0x100];

	for (i = 0; i < ARRAY_SIZE(about_lines); i++) {
		for (j = 0; j < strlen(about_lines[i]); j++) {
			if (linecd[i][j] > 60) {
				buf[j] = ' ';
				linecd[i][j]--;
			} else if (linecd[i][j]) {
				buf[j] = (rand() / (float)RAND_MAX) * 54 + 65;
				linecd[i][j]--;
			} else {
				buf[j] = about_lines[i][j];
			}
		}
		buf[j] = '\0';
		waddstr_center(w_about, (WAV_HEIGHT - ARRAY_SIZE(about_lines))/2 + i, buf);
	}
	wrefresh(w_about);
	return wgetch(w_menu);
}

void scr_about_fini(void)
{
	delwin(w_about);
	for (i = 0; i < ARRAY_SIZE(about_lines); i++)
		free(linecd[i]);
}
span> += snprintf(buf + len, buflen - len, "%2d/%d", cur->qual.qual, iw_range->max_qual.qual); else if (!(cur->qual.updated & IW_QUAL_LEVEL_INVALID)) len += snprintf(buf + len, buflen - len, "%.0f dBm", dbm.signal); else len += snprintf(buf + len, buflen - len, "? dBm"); if (cur->freq < 1e3) len += snprintf(buf + len, buflen - len, ", Chan %2.0f", cur->freq); else if (channel >= 0 && cur->freq < 5e9) len += snprintf(buf + len, buflen - len, ", ch %2d, %g MHz", channel, cur->freq / 1e6); else if (channel >= 0) len += snprintf(buf + len, buflen - len, ", CH %3d, %g MHz", channel, cur->freq / 1e6); else len += snprintf(buf + len, buflen - len, ", %g GHz", cur->freq / 1e9); /* Access Points are marked by CP_SCAN_CRYPT/CP_SCAN_UNENC already */ if (cur->mode != IW_MODE_MASTER) len += snprintf(buf + len, buflen - len, " %s", iw_opmode(cur->mode)); if (cur->flags) len += snprintf(buf + len, buflen - len, ", %s", format_enc_capab(cur->flags, "/")); return buf; } static void display_aplist(WINDOW *w_aplst) { char s[IW_ESSID_MAX_SIZE << 3]; int max_essid_len = 0; int i, line = START_LINE; int total = 0, open = 0, tg = 0, fg = 0; struct iw_range range; struct scan_result *head, *cur; struct cnt *stats; int max_cnt = NUMTOP; int skfd = socket(AF_INET, SOCK_DGRAM, 0); if (skfd < 0) err_sys("%s: can not open socket", __func__); iw_getinf_range(conf_ifname(), &range); head = get_scan_list(skfd, conf_ifname(), range.we_version_compiled); if (head) { ; } else if (errno == EPERM || !has_net_admin_capability()) { /* * Don't try to read leftover results, it does not work reliably */ sprintf(s, "This screen requires CAP_NET_ADMIN permissions"); } else if (errno == EINTR || errno == EAGAIN || errno == EBUSY) { /* Ignore temporary errors */ goto done; } else if (!if_is_up(skfd, conf_ifname())) { sprintf(s, "Interface '%s' is down ", conf_ifname()); if (!has_net_admin_capability()) strcat(s, "- can not scan"); else if (if_set_up(skfd, conf_ifname()) < 0) sprintf(s, "Can not bring up '%s' for scanning: %s", conf_ifname(), strerror(errno)); else strcat(s, "- setting it up ..."); } else if (errno == EFAULT) { /* * EFAULT can occur after a window resizing event and is temporary. * It may also occur when the interface is down, hence we need to * test the interface status first. */ goto done; } else if (errno) { sprintf(s, "No scan on %s: %s", conf_ifname(), strerror(errno)); } else { sprintf(s, "No scan results on %s", conf_ifname()); } for (i = 1; i <= MAXYLEN; i++) mvwclrtoborder(w_aplst, i, 1); if (!head) waddstr_center(w_aplst, WAV_HEIGHT/2 - 1, s); for (cur = head; cur; cur = cur->next, total++) { if (str_is_ascii(cur->essid)) max_essid_len = clamp(strlen(cur->essid), max_essid_len, IW_ESSID_MAX_SIZE); open += ! cur->has_key; if (cur->freq < 1e3) ; /* cur->freq is channel number */ else if (cur->freq < 5e9) tg++; else fg++; } /* Truncate overly long access point lists to match screen height */ for (cur = head; cur && line < MAXYLEN; line++, cur = cur->next) { int col = CP_SCAN_NON_AP; if (cur->mode == IW_MODE_MASTER) col = cur->has_key ? CP_SCAN_CRYPT : CP_SCAN_UNENC; wmove(w_aplst, line, 1); if (!*cur->essid) { sprintf(s, "%-*s ", max_essid_len, "<hidden ESSID>"); wattron(w_aplst, COLOR_PAIR(col)); waddstr(w_aplst, s); } else if (str_is_ascii(cur->essid)) { sprintf(s, "%-*s ", max_essid_len, cur->essid); waddstr_b(w_aplst, s); wattron(w_aplst, COLOR_PAIR(col)); } else { sprintf(s, "%-*s ", max_essid_len, "<cryptic ESSID>"); wattron(w_aplst, COLOR_PAIR(col)); waddstr(w_aplst, s); } waddstr(w_aplst, ether_addr(&cur->ap_addr)); wattroff(w_aplst, COLOR_PAIR(col)); fmt_scan_result(cur, &range, s, sizeof(s)); waddstr(w_aplst, " "); waddstr(w_aplst, s); } /* Summary statistics at the bottom. */ if (total < NUMTOP) goto done; wmove(w_aplst, MAXYLEN, 1); wadd_attr_str(w_aplst, A_REVERSE, "total:"); sprintf(s, " %d", total); waddstr(w_aplst, s); if (total + START_LINE > line) { sprintf(s, " (%d not shown)", total + START_LINE - line); waddstr(w_aplst, s); } if (open) { sprintf(s, ", %d open", open); waddstr(w_aplst, s); } if (tg && fg) { waddch(w_aplst, ' '); wadd_attr_str(w_aplst, A_REVERSE, "5/2GHz:"); sprintf(s, " %d/%d", fg, tg); waddstr(w_aplst, s); } stats = channel_stats(head, &range, &max_cnt); if (stats) { waddch(w_aplst, ' '); if (conf.scan_sort_order == SO_CHAN_REV) sprintf(s, "bottom-%d:", max_cnt); else sprintf(s, "top-%d:", max_cnt); wadd_attr_str(w_aplst, A_REVERSE, s); for (i = 0; i < max_cnt; i++) { sprintf(s, "%s CH-%d(%d)", i ? "," : "", stats[i].val, stats[i].count); waddstr(w_aplst, s); } } free(stats); done: free_scan_result(head); close(skfd); wrefresh(w_aplst); } void scr_aplst_init(void) { w_aplst = newwin_title(0, WAV_HEIGHT, "Scan window", false); /* * Both parent and child process write to the terminal, updating * different areas of the screen. Suspending wavemon brings the * terminal state out of order, messing up the screen. The choice * is between a more complicated (sophisticated) handling of * signals, and to keep it simple by not allowing to suspend. */ sig_tstp = xsignal(SIGTSTP, SIG_IGN); /* Gathering scan data can take seconds. Inform user. */ mvwaddstr(w_aplst, START_LINE, 1, "Waiting for scan data ..."); wrefresh(w_aplst); pid = fork(); if (pid < 0) { err_sys("could not fork scan process"); } else if (pid == 0) { do display_aplist(w_aplst); while (usleep(conf.stat_iv * 1000) == 0); exit(EXIT_SUCCESS); } } int scr_aplst_loop(WINDOW *w_menu) { return wgetch(w_menu); } void scr_aplst_fini(void) { kill(pid, SIGTERM); delwin(w_aplst); xsignal(SIGTSTP, sig_tstp); }