wpa_cli: Replace CONFIG_WPA_CLI_FORK design with eloop

Instead of using a separate process to receive and print event
messages, use a single-process design with eloop to simply
wpa_cli and interaction with readline.
This commit is contained in:
Jouni Malinen 2010-11-14 13:16:51 +02:00
parent 6f1c6549ed
commit cd10156798
2 changed files with 143 additions and 197 deletions

View file

@ -89,6 +89,7 @@ ifndef CONFIG_ELOOP
CONFIG_ELOOP=eloop CONFIG_ELOOP=eloop
endif endif
OBJS += ../src/utils/$(CONFIG_ELOOP).o OBJS += ../src/utils/$(CONFIG_ELOOP).o
OBJS_c += ../src/utils/$(CONFIG_ELOOP).o
ifdef CONFIG_EAPOL_TEST ifdef CONFIG_EAPOL_TEST

View file

@ -23,12 +23,10 @@
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#endif /* CONFIG_READLINE */ #endif /* CONFIG_READLINE */
#ifdef CONFIG_WPA_CLI_FORK
#include <sys/wait.h>
#endif /* CONFIG_WPA_CLI_FORK */
#include "common/wpa_ctrl.h" #include "common/wpa_ctrl.h"
#include "common.h" #include "utils/common.h"
#include "utils/eloop.h"
#include "common/version.h" #include "common/version.h"
@ -91,9 +89,6 @@ static const char *wpa_cli_full_license =
static struct wpa_ctrl *ctrl_conn; static struct wpa_ctrl *ctrl_conn;
static struct wpa_ctrl *mon_conn; static struct wpa_ctrl *mon_conn;
#ifdef CONFIG_WPA_CLI_FORK
static pid_t mon_pid = 0;
#endif /* CONFIG_WPA_CLI_FORK */
static int wpa_cli_quit = 0; static int wpa_cli_quit = 0;
static int wpa_cli_attached = 0; static int wpa_cli_attached = 0;
static int wpa_cli_connected = 0; static int wpa_cli_connected = 0;
@ -104,9 +99,14 @@ static const char *pid_file = NULL;
static const char *action_file = NULL; static const char *action_file = NULL;
static int ping_interval = 5; static int ping_interval = 5;
static int interactive = 0; static int interactive = 0;
#ifndef CONFIG_READLINE
static char cmdbuf[256];
static int cmdbuf_pos = 0;
#endif /* CONFIG_READLINE */
static void print_help(); static void print_help(void);
static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
static void usage(void) static void usage(void)
@ -132,6 +132,10 @@ static void readline_redraw()
#ifdef CONFIG_READLINE #ifdef CONFIG_READLINE
rl_on_new_line(); rl_on_new_line();
rl_redisplay(); rl_redisplay();
#else /* CONFIG_READLINE */
cmdbuf[cmdbuf_pos] = '\0';
printf("\r> %s", cmdbuf);
fflush(stdout);
#endif /* CONFIG_READLINE */ #endif /* CONFIG_READLINE */
} }
@ -163,64 +167,6 @@ static int wpa_cli_show_event(const char *event)
} }
#ifdef CONFIG_WPA_CLI_FORK
static int in_query = 0;
static void wpa_cli_monitor_sig(int sig)
{
if (sig == SIGUSR1)
in_query = 1;
else if (sig == SIGUSR2)
in_query = 0;
}
static void wpa_cli_monitor(void)
{
char buf[256];
size_t len = sizeof(buf) - 1;
struct timeval tv;
fd_set rfds;
int ppid;
signal(SIGUSR1, wpa_cli_monitor_sig);
signal(SIGUSR2, wpa_cli_monitor_sig);
ppid = getppid();
while (mon_conn) {
int s = wpa_ctrl_get_fd(mon_conn);
tv.tv_sec = 5;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(s, &rfds);
if (select(s + 1, &rfds, NULL, NULL, &tv) < 0) {
if (errno == EINTR)
continue;
perror("select");
break;
}
if (mon_conn == NULL)
break;
if (FD_ISSET(s, &rfds)) {
len = sizeof(buf) - 1;
int res = wpa_ctrl_recv(mon_conn, buf, &len);
if (res < 0) {
perror("wpa_ctrl_recv");
break;
}
buf[len] = '\0';
if (wpa_cli_show_event(buf)) {
if (in_query)
printf("\r");
printf("%s\n", buf);
kill(ppid, SIGUSR1);
}
}
}
}
#endif /* CONFIG_WPA_CLI_FORK */
static int wpa_cli_open_connection(const char *ifname, int attach) static int wpa_cli_open_connection(const char *ifname, int attach)
{ {
#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
@ -265,26 +211,15 @@ static int wpa_cli_open_connection(const char *ifname, int attach)
if (mon_conn) { if (mon_conn) {
if (wpa_ctrl_attach(mon_conn) == 0) { if (wpa_ctrl_attach(mon_conn) == 0) {
wpa_cli_attached = 1; wpa_cli_attached = 1;
if (interactive)
eloop_register_read_sock(
wpa_ctrl_get_fd(mon_conn),
wpa_cli_mon_receive, NULL, NULL);
} else { } else {
printf("Warning: Failed to attach to " printf("Warning: Failed to attach to "
"wpa_supplicant.\n"); "wpa_supplicant.\n");
return -1; return -1;
} }
#ifdef CONFIG_WPA_CLI_FORK
{
pid_t p = fork();
if (p < 0) {
perror("fork");
return -1;
}
if (p == 0) {
wpa_cli_monitor();
exit(0);
} else
mon_pid = p;
}
#endif /* CONFIG_WPA_CLI_FORK */
} }
return 0; return 0;
@ -296,15 +231,6 @@ static void wpa_cli_close_connection(void)
if (ctrl_conn == NULL) if (ctrl_conn == NULL)
return; return;
#ifdef CONFIG_WPA_CLI_FORK
if (mon_pid) {
int status;
kill(mon_pid, SIGPIPE);
wait(&status);
mon_pid = 0;
}
#endif /* CONFIG_WPA_CLI_FORK */
if (wpa_cli_attached) { if (wpa_cli_attached) {
wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
wpa_cli_attached = 0; wpa_cli_attached = 0;
@ -312,6 +238,7 @@ static void wpa_cli_close_connection(void)
wpa_ctrl_close(ctrl_conn); wpa_ctrl_close(ctrl_conn);
ctrl_conn = NULL; ctrl_conn = NULL;
if (mon_conn) { if (mon_conn) {
eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
wpa_ctrl_close(mon_conn); wpa_ctrl_close(mon_conn);
mon_conn = NULL; mon_conn = NULL;
} }
@ -413,6 +340,8 @@ static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
{ {
wpa_cli_quit = 1; wpa_cli_quit = 1;
if (interactive)
eloop_terminate();
return 0; return 0;
} }
@ -2697,10 +2626,8 @@ static void wpa_cli_reconnect(void)
} }
static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
int action_monitor)
{ {
int first = 1;
if (ctrl_conn == NULL) { if (ctrl_conn == NULL) {
wpa_cli_reconnect(); wpa_cli_reconnect();
return; return;
@ -2714,10 +2641,7 @@ static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
wpa_cli_action_process(buf); wpa_cli_action_process(buf);
else { else {
if (wpa_cli_show_event(buf)) { if (wpa_cli_show_event(buf)) {
if (in_read && first) printf("\r%s\n", buf);
printf("\r");
first = 0;
printf("%s\n", buf);
readline_redraw(); readline_redraw();
} }
} }
@ -2779,6 +2703,31 @@ static void trunc_nl(char *str)
} }
static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
printf("Connection to wpa_supplicant lost - trying to "
"reconnect\n");
wpa_cli_close_connection();
}
if (!ctrl_conn)
wpa_cli_reconnect();
eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
}
static void wpa_cli_eloop_terminate(int sig, void *signal_ctx)
{
eloop_terminate();
}
static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
wpa_cli_recv_pending(mon_conn, 0);
}
#ifdef CONFIG_READLINE #ifdef CONFIG_READLINE
static char * wpa_cli_cmd_gen(const char *text, int state) static char * wpa_cli_cmd_gen(const char *text, int state)
@ -2859,10 +2808,39 @@ static char ** wpa_cli_completion(const char *text, int start, int end)
} }
static void wpa_cli_read_char(int sock, void *eloop_ctx, void *sock_ctx)
{
rl_callback_read_char();
}
static void readline_cmd_handler(char *cmd)
{
int argc;
char *argv[max_args];
if (cmd && *cmd) {
HIST_ENTRY *h;
while (next_history())
;
h = previous_history();
if (h == NULL || os_strcmp(cmd, h->line) != 0)
add_history(cmd);
next_history();
}
if (cmd == NULL) {
eloop_terminate();
return;
}
trunc_nl(cmd);
argc = tokenize_cmd(cmd, argv);
if (argc)
wpa_request(ctrl_conn, argc, argv);
}
static void wpa_cli_interactive(void) static void wpa_cli_interactive(void)
{ {
char cmdbuf[256], *cmd, *argv[max_args];
int argc;
char *home, *hfile = NULL; char *home, *hfile = NULL;
printf("\nInteractive mode\n\n"); printf("\nInteractive mode\n\n");
@ -2885,43 +2863,19 @@ static void wpa_cli_interactive(void)
} }
} }
do { eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
wpa_cli_recv_pending(mon_conn, 0, 0); eloop_register_read_sock(STDIN_FILENO, wpa_cli_read_char, NULL, NULL);
#ifndef CONFIG_NATIVE_WINDOWS eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
alarm(ping_interval);
#endif /* CONFIG_NATIVE_WINDOWS */
#ifdef CONFIG_WPA_CLI_FORK
if (mon_pid)
kill(mon_pid, SIGUSR1);
#endif /* CONFIG_WPA_CLI_FORK */
cmd = readline("> ");
if (cmd && *cmd) {
HIST_ENTRY *h;
while (next_history())
;
h = previous_history();
if (h == NULL || os_strcmp(cmd, h->line) != 0)
add_history(cmd);
next_history();
}
#ifndef CONFIG_NATIVE_WINDOWS
alarm(0);
#endif /* CONFIG_NATIVE_WINDOWS */
if (cmd == NULL)
break;
wpa_cli_recv_pending(mon_conn, 0, 0);
trunc_nl(cmd);
argc = tokenize_cmd(cmd, argv);
if (argc)
wpa_request(ctrl_conn, argc, argv);
if (cmd != cmdbuf) rl_callback_handler_install("> ", readline_cmd_handler);
free(cmd);
#ifdef CONFIG_WPA_CLI_FORK eloop_run();
if (mon_pid)
kill(mon_pid, SIGUSR2); rl_callback_handler_remove();
#endif /* CONFIG_WPA_CLI_FORK */
} while (!wpa_cli_quit); eloop_unregister_read_sock(STDIN_FILENO);
eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
wpa_cli_close_connection();
if (hfile) { if (hfile) {
/* Save command history, excluding lines that may contain /* Save command history, excluding lines that may contain
@ -2936,7 +2890,7 @@ static void wpa_cli_interactive(void)
h = remove_history(where_history()); h = remove_history(where_history());
if (h) { if (h) {
os_free(h->line); os_free(h->line);
os_free(h->data); free(h->data);
os_free(h); os_free(h);
} else } else
next_history(); next_history();
@ -2950,42 +2904,60 @@ static void wpa_cli_interactive(void)
#else /* CONFIG_READLINE */ #else /* CONFIG_READLINE */
static void wpa_cli_interactive(void) static void wpa_cli_read_char(int sock, void *eloop_ctx, void *sock_ctx)
{ {
char cmdbuf[256], *cmd, *argv[max_args]; char *argv[max_args];
int argc; int argc;
int c;
char buf[1];
int res;
printf("\nInteractive mode\n\n"); res = read(sock, buf, 1);
if (res < 0)
perror("read");
if (res <= 0) {
eloop_terminate();
return;
}
c = buf[0];
do { if (c == '\r' || c == '\n') {
wpa_cli_recv_pending(mon_conn, 0, 0); cmdbuf[cmdbuf_pos] = '\0';
#ifndef CONFIG_NATIVE_WINDOWS cmdbuf_pos = 0;
alarm(ping_interval); trunc_nl(cmdbuf);
#endif /* CONFIG_NATIVE_WINDOWS */ argc = tokenize_cmd(cmdbuf, argv);
#ifdef CONFIG_WPA_CLI_FORK
if (mon_pid)
kill(mon_pid, SIGUSR1);
#endif /* CONFIG_WPA_CLI_FORK */
printf("> ");
cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
#ifndef CONFIG_NATIVE_WINDOWS
alarm(0);
#endif /* CONFIG_NATIVE_WINDOWS */
if (cmd == NULL)
break;
wpa_cli_recv_pending(mon_conn, 0, 0);
trunc_nl(cmd);
argc = tokenize_cmd(cmd, argv);
if (argc) if (argc)
wpa_request(ctrl_conn, argc, argv); wpa_request(ctrl_conn, argc, argv);
printf("> ");
fflush(stdout);
return;
}
if (cmd != cmdbuf) if (c >= 32 && c <= 255) {
free(cmd); if (cmdbuf_pos < (int) sizeof(cmdbuf) - 1) {
#ifdef CONFIG_WPA_CLI_FORK cmdbuf[cmdbuf_pos++] = c;
if (mon_pid) }
kill(mon_pid, SIGUSR2); }
#endif /* CONFIG_WPA_CLI_FORK */ }
} while (!wpa_cli_quit);
static void wpa_cli_interactive(void)
{
printf("\nInteractive mode\n\n");
cmdbuf_pos = 0;
eloop_register_signal_terminate(wpa_cli_eloop_terminate, NULL);
eloop_register_read_sock(STDIN_FILENO, wpa_cli_read_char, NULL, NULL);
eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
printf("> ");
fflush(stdout);
eloop_run();
eloop_unregister_read_sock(STDIN_FILENO);
eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
wpa_cli_close_connection();
} }
#endif /* CONFIG_READLINE */ #endif /* CONFIG_READLINE */
@ -3017,7 +2989,7 @@ static void wpa_cli_action(struct wpa_ctrl *ctrl)
} }
if (FD_ISSET(fd, &rfds)) if (FD_ISSET(fd, &rfds))
wpa_cli_recv_pending(ctrl, 0, 1); wpa_cli_recv_pending(ctrl, 1);
else { else {
/* verify that connection is still working */ /* verify that connection is still working */
len = sizeof(buf) - 1; len = sizeof(buf) - 1;
@ -3050,31 +3022,6 @@ static void wpa_cli_terminate(int sig)
} }
#ifdef CONFIG_WPA_CLI_FORK
static void wpa_cli_usr1(int sig)
{
readline_redraw();
}
#endif /* CONFIG_WPA_CLI_FORK */
#ifndef CONFIG_NATIVE_WINDOWS
static void wpa_cli_alarm(int sig)
{
if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
printf("Connection to wpa_supplicant lost - trying to "
"reconnect\n");
wpa_cli_close_connection();
}
if (!ctrl_conn)
wpa_cli_reconnect();
if (mon_conn)
wpa_cli_recv_pending(mon_conn, 1, 0);
alarm(ping_interval);
}
#endif /* CONFIG_NATIVE_WINDOWS */
static char * wpa_cli_get_default_ifname(void) static char * wpa_cli_get_default_ifname(void)
{ {
char *ifname = NULL; char *ifname = NULL;
@ -3185,6 +3132,9 @@ int main(int argc, char *argv[])
if (interactive) if (interactive)
printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license); printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
if (eloop_init())
return -1;
if (global) { if (global) {
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
ctrl_conn = wpa_ctrl_open(NULL); ctrl_conn = wpa_ctrl_open(NULL);
@ -3202,12 +3152,6 @@ int main(int argc, char *argv[])
signal(SIGINT, wpa_cli_terminate); signal(SIGINT, wpa_cli_terminate);
signal(SIGTERM, wpa_cli_terminate); signal(SIGTERM, wpa_cli_terminate);
#endif /* _WIN32_WCE */ #endif /* _WIN32_WCE */
#ifndef CONFIG_NATIVE_WINDOWS
signal(SIGALRM, wpa_cli_alarm);
#endif /* CONFIG_NATIVE_WINDOWS */
#ifdef CONFIG_WPA_CLI_FORK
signal(SIGUSR1, wpa_cli_usr1);
#endif /* CONFIG_WPA_CLI_FORK */
if (ctrl_ifname == NULL) if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname(); ctrl_ifname = wpa_cli_get_default_ifname();
@ -3258,6 +3202,7 @@ int main(int argc, char *argv[])
ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]); ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
os_free(ctrl_ifname); os_free(ctrl_ifname);
eloop_destroy();
wpa_cli_cleanup(); wpa_cli_cleanup();
return ret; return ret;