]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/wpa_cli.c
This commit was generated by cvs2svn to compensate for changes in r147899,
[FreeBSD/FreeBSD.git] / contrib / wpa_supplicant / wpa_cli.c
1 /*
2  * WPA Supplicant - command line interface for wpa_supplicant daemon
3  * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <signal.h>
19 #include <unistd.h>
20 #include <dirent.h>
21 #ifdef CONFIG_READLINE
22 #include <readline/readline.h>
23 #include <readline/history.h>
24 #endif /* CONFIG_READLINE */
25
26 #include "wpa_ctrl.h"
27 #ifdef CONFIG_NATIVE_WINDOWS
28 #include "common.h"
29 #endif /* CONFIG_NATIVE_WINDOWS */
30 #include "version.h"
31
32
33 static const char *wpa_cli_version =
34 "wpa_cli v" VERSION_STR "\n"
35 "Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> and contributors";
36
37
38 static const char *wpa_cli_license =
39 "This program is free software. You can distribute it and/or modify it\n"
40 "under the terms of the GNU General Public License version 2.\n"
41 "\n"
42 "Alternatively, this software may be distributed under the terms of the\n"
43 "BSD license. See README and COPYING for more details.\n";
44
45 static const char *wpa_cli_full_license =
46 "This program is free software; you can redistribute it and/or modify\n"
47 "it under the terms of the GNU General Public License version 2 as\n"
48 "published by the Free Software Foundation.\n"
49 "\n"
50 "This program is distributed in the hope that it will be useful,\n"
51 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
52 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
53 "GNU General Public License for more details.\n"
54 "\n"
55 "You should have received a copy of the GNU General Public License\n"
56 "along with this program; if not, write to the Free Software\n"
57 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
58 "\n"
59 "Alternatively, this software may be distributed under the terms of the\n"
60 "BSD license.\n"
61 "\n"
62 "Redistribution and use in source and binary forms, with or without\n"
63 "modification, are permitted provided that the following conditions are\n"
64 "met:\n"
65 "\n"
66 "1. Redistributions of source code must retain the above copyright\n"
67 "   notice, this list of conditions and the following disclaimer.\n"
68 "\n"
69 "2. Redistributions in binary form must reproduce the above copyright\n"
70 "   notice, this list of conditions and the following disclaimer in the\n"
71 "   documentation and/or other materials provided with the distribution.\n"
72 "\n"
73 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
74 "   names of its contributors may be used to endorse or promote products\n"
75 "   derived from this software without specific prior written permission.\n"
76 "\n"
77 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
78 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
79 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
80 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
81 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
82 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
83 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
84 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
85 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
86 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
87 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
88 "\n";
89
90 static const char *commands_help =
91 "commands:\n"
92 "  status [verbose] = get current WPA/EAPOL/EAP status\n"
93 "  mib = get MIB variables (dot1x, dot11)\n"
94 "  help = show this usage help\n"
95 "  interface [ifname] = show interfaces/select interface\n"
96 "  level <debug level> = change debug level\n"
97 "  license = show full wpa_cli license\n"
98 "  logoff = IEEE 802.1X EAPOL state machine logoff\n"
99 "  logon = IEEE 802.1X EAPOL state machine logon\n"
100 "  set = set variables (shows list of variables when run without arguments)\n"
101 "  pmksa = show PMKSA cache\n"
102 "  reassociate = force reassociation\n"
103 "  reconfigure = force wpa_supplicant to re-read its configuration file\n"
104 "  preauthenticate <BSSID> = force preauthentication\n"
105 "  identity <network id> <identity> = configure identity for an SSID\n"
106 "  password <network id> <password> = configure password for an SSID\n"
107 "  otp <network id> <password> = configure one-time-password for an SSID\n"
108 "  terminate = terminate wpa_supplicant\n"
109 "  quit = exit wpa_cli\n";
110
111 static struct wpa_ctrl *ctrl_conn;
112 static int wpa_cli_quit = 0;
113 static int wpa_cli_attached = 0;
114 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
115 static char *ctrl_ifname = NULL;
116
117
118 static void usage(void)
119 {
120         printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hv] "
121                "[command..]\n"
122                "  -h = help (show this usage text)\n"
123                "  -v = shown version information\n"
124                "  default path: /var/run/wpa_supplicant\n"
125                "  default interface: first interface found in socket path\n"
126                "%s",
127                commands_help);
128 }
129
130
131 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
132 {
133 #ifdef CONFIG_CTRL_IFACE_UDP
134         ctrl_conn = wpa_ctrl_open("");
135         return ctrl_conn;
136 #else /* CONFIG_CTRL_IFACE_UDP */
137         char *cfile;
138         int flen;
139
140         if (ifname == NULL)
141                 return NULL;
142
143         flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
144         cfile = malloc(flen);
145         if (cfile == NULL)
146                 return NULL;
147         snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
148
149         ctrl_conn = wpa_ctrl_open(cfile);
150         free(cfile);
151         return ctrl_conn;
152 #endif /* CONFIG_CTRL_IFACE_UDP */
153 }
154
155
156 static void wpa_cli_close_connection(void)
157 {
158         if (ctrl_conn == NULL)
159                 return;
160
161         if (wpa_cli_attached) {
162                 wpa_ctrl_detach(ctrl_conn);
163                 wpa_cli_attached = 0;
164         }
165         wpa_ctrl_close(ctrl_conn);
166         ctrl_conn = NULL;
167 }
168
169
170 static void wpa_cli_msg_cb(char *msg, size_t len)
171 {
172         printf("%s\n", msg);
173 }
174
175
176 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
177 {
178         char buf[2048];
179         size_t len;
180         int ret;
181
182         if (ctrl_conn == NULL) {
183                 printf("Not connected to wpa_supplicant - command dropped.\n");
184                 return -1;
185         }
186         len = sizeof(buf) - 1;
187         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
188                                wpa_cli_msg_cb);
189         if (ret == -2) {
190                 printf("'%s' command timed out.\n", cmd);
191                 return -2;
192         } else if (ret < 0) {
193                 printf("'%s' command failed.\n", cmd);
194                 return -1;
195         }
196         if (print) {
197                 buf[len] = '\0';
198                 printf("%s", buf);
199         }
200         return 0;
201 }
202
203
204 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
205 {
206         return _wpa_ctrl_command(ctrl, cmd, 1);
207 }
208
209
210 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
211 {
212         int verbose = argc > 0 && strcmp(argv[0], "verbose") == 0;
213         return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
214 }
215
216
217 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
218 {
219         return wpa_ctrl_command(ctrl, "PING");
220 }
221
222
223 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
224 {
225         return wpa_ctrl_command(ctrl, "MIB");
226 }
227
228
229 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
230 {
231         return wpa_ctrl_command(ctrl, "PMKSA");
232 }
233
234
235 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
236 {
237         printf("%s", commands_help);
238         return 0;
239 }
240
241
242 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
243 {
244         printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
245         return 0;
246 }
247
248
249 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
250 {
251         wpa_cli_quit = 1;
252         return 0;
253 }
254
255
256 static void wpa_cli_show_variables(void)
257 {
258         printf("set variables:\n"
259                "  EAPOL::heldPeriod (EAPOL state machine held period, "
260                "in seconds)\n"
261                "  EAPOL::authPeriod (EAPOL state machine authentication "
262                "period, in seconds)\n"
263                "  EAPOL::startPeriod (EAPOL state machine start period, in "
264                "seconds)\n"
265                "  EAPOL::maxStart (EAPOL state machine maximum start "
266                "attempts)\n");
267 }
268
269
270 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
271 {
272         char cmd[256];
273
274         if (argc == 0) {
275                 wpa_cli_show_variables();
276                 return 0;
277         }
278
279         if (argc != 2) {
280                 printf("Invalid SET command: needs two arguments (variable "
281                        "name and value)\n");
282                 return 0;
283         }
284
285         if (snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]) >=
286             sizeof(cmd) - 1) {
287                 printf("Too long SET command.\n");
288                 return 0;
289         }
290         return wpa_ctrl_command(ctrl, cmd);
291 }
292
293
294 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
295 {
296         return wpa_ctrl_command(ctrl, "LOGOFF");
297 }
298
299
300 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
301 {
302         return wpa_ctrl_command(ctrl, "LOGON");
303 }
304
305
306 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
307                                    char *argv[])
308 {
309         return wpa_ctrl_command(ctrl, "REASSOCIATE");
310 }
311
312
313 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
314                                        char *argv[])
315 {
316         char cmd[256];
317
318         if (argc != 1) {
319                 printf("Invalid PREAUTH command: needs one argument "
320                        "(BSSID)\n");
321                 return 0;
322         }
323
324         if (snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]) >=
325             sizeof(cmd) - 1) {
326                 printf("Too long PREAUTH command.\n");
327                 return 0;
328         }
329         return wpa_ctrl_command(ctrl, cmd);
330 }
331
332
333 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
334 {
335         char cmd[256];
336         if (argc != 1) {
337                 printf("Invalid LEVEL command: needs one argument (debug "
338                        "level)\n");
339                 return 0;
340         }
341         snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
342         return wpa_ctrl_command(ctrl, cmd);
343 }
344
345
346 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
347 {
348         char cmd[256], *pos, *end;
349         int i;
350
351         if (argc < 2) {
352                 printf("Invalid IDENTITY command: needs two arguments "
353                        "(network id and identity)\n");
354                 return 0;
355         }
356
357         end = cmd + sizeof(cmd);
358         pos = cmd;
359         pos += snprintf(pos, end - pos, "CTRL-RSP-IDENTITY-%s:%s",
360                        argv[0], argv[1]);
361         for (i = 2; i < argc; i++)
362                 pos += snprintf(pos, end - pos, " %s", argv[i]);
363
364         return wpa_ctrl_command(ctrl, cmd);
365 }
366
367
368 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
369 {
370         char cmd[256], *pos, *end;
371         int i;
372
373         if (argc < 2) {
374                 printf("Invalid PASSWORD command: needs two arguments "
375                        "(network id and password)\n");
376                 return 0;
377         }
378
379         end = cmd + sizeof(cmd);
380         pos = cmd;
381         pos += snprintf(pos, end - pos, "CTRL-RSP-PASSWORD-%s:%s",
382                        argv[0], argv[1]);
383         for (i = 2; i < argc; i++)
384                 pos += snprintf(pos, end - pos, " %s", argv[i]);
385
386         return wpa_ctrl_command(ctrl, cmd);
387 }
388
389
390 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
391 {
392         char cmd[256], *pos, *end;
393         int i;
394
395         if (argc < 2) {
396                 printf("Invalid OTP command: needs two arguments (network "
397                        "id and password)\n");
398                 return 0;
399         }
400
401         end = cmd + sizeof(cmd);
402         pos = cmd;
403         pos += snprintf(pos, end - pos, "CTRL-RSP-OTP-%s:%s",
404                        argv[0], argv[1]);
405         for (i = 2; i < argc; i++)
406                 pos += snprintf(pos, end - pos, " %s", argv[i]);
407
408         return wpa_ctrl_command(ctrl, cmd);
409 }
410
411
412 static void wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
413 {
414         struct dirent *dent;
415         DIR *dir;
416
417         dir = opendir(ctrl_iface_dir);
418         if (dir == NULL) {
419                 printf("Control interface directory '%s' could not be "
420                        "openned.\n", ctrl_iface_dir);
421                 return;
422         }
423
424         printf("Available interfaces:\n");
425         while ((dent = readdir(dir))) {
426                 if (strcmp(dent->d_name, ".") == 0 ||
427                     strcmp(dent->d_name, "..") == 0)
428                         continue;
429                 printf("%s\n", dent->d_name);
430         }
431         closedir(dir);
432 }
433
434
435 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
436 {
437         if (argc < 1) {
438                 wpa_cli_list_interfaces(ctrl);
439                 return 0;
440         }
441
442         wpa_cli_close_connection();
443         free(ctrl_ifname);
444         ctrl_ifname = strdup(argv[0]);
445
446         if (wpa_cli_open_connection(ctrl_ifname)) {
447                 printf("Connected to interface '%s.\n", ctrl_ifname);
448                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
449                         wpa_cli_attached = 1;
450                 } else {
451                         printf("Warning: Failed to attach to "
452                                "wpa_supplicant.\n");
453                 }
454         } else {
455                 printf("Could not connect to interface '%s' - re-trying\n",
456                         ctrl_ifname);
457         }
458         return 0;
459 }
460
461
462 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
463                                    char *argv[])
464 {
465         return wpa_ctrl_command(ctrl, "RECONFIGURE");
466 }
467
468
469 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
470                                  char *argv[])
471 {
472         return wpa_ctrl_command(ctrl, "TERMINATE");
473 }
474
475
476 struct wpa_cli_cmd {
477         const char *cmd;
478         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
479 };
480
481 static struct wpa_cli_cmd wpa_cli_commands[] = {
482         { "status", wpa_cli_cmd_status },
483         { "ping", wpa_cli_cmd_ping },
484         { "mib", wpa_cli_cmd_mib },
485         { "help", wpa_cli_cmd_help },
486         { "interface", wpa_cli_cmd_interface },
487         { "level", wpa_cli_cmd_level },
488         { "license", wpa_cli_cmd_license },
489         { "quit", wpa_cli_cmd_quit },
490         { "set", wpa_cli_cmd_set },
491         { "logon", wpa_cli_cmd_logon },
492         { "logoff", wpa_cli_cmd_logoff },
493         { "pmksa", wpa_cli_cmd_pmksa },
494         { "reassociate", wpa_cli_cmd_reassociate },
495         { "preauthenticate", wpa_cli_cmd_preauthenticate },
496         { "identity", wpa_cli_cmd_identity },
497         { "password", wpa_cli_cmd_password },
498         { "otp", wpa_cli_cmd_otp },
499         { "reconfigure", wpa_cli_cmd_reconfigure },
500         { "terminate", wpa_cli_cmd_terminate },
501         { NULL, NULL }
502 };
503
504
505 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
506 {
507         struct wpa_cli_cmd *cmd, *match = NULL;
508         int count;
509
510         count = 0;
511         cmd = wpa_cli_commands;
512         while (cmd->cmd) {
513                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
514                         match = cmd;
515                         count++;
516                 }
517                 cmd++;
518         }
519
520         if (count > 1) {
521                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
522                 cmd = wpa_cli_commands;
523                 while (cmd->cmd) {
524                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
525                             0) {
526                                 printf(" %s", cmd->cmd);
527                         }
528                         cmd++;
529                 }
530                 printf("\n");
531         } else if (count == 0) {
532                 printf("Unknown command '%s'\n", argv[0]);
533         } else {
534                 match->handler(ctrl, argc - 1, &argv[1]);
535         }
536 }
537
538
539 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read)
540 {
541         int first = 1;
542         if (ctrl_conn == NULL)
543                 return;
544         while (wpa_ctrl_pending(ctrl)) {
545                 char buf[256];
546                 size_t len = sizeof(buf) - 1;
547                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
548                         buf[len] = '\0';
549                         if (in_read && first)
550                                 printf("\n");
551                         first = 0;
552                         printf("%s\n", buf);
553                 } else {
554                         printf("Could not read pending message.\n");
555                         break;
556                 }
557         }
558 }
559
560
561 #ifdef CONFIG_READLINE
562 static char * wpa_cli_cmd_gen(const char *text, int state)
563 {
564         static int i, len;
565         const char *cmd;
566
567         if (state == 0) {
568                 i = 0;
569                 len = strlen(text);
570         }
571
572         while ((cmd = wpa_cli_commands[i].cmd)) {
573                 i++;
574                 if (strncasecmp(cmd, text, len) == 0)
575                         return strdup(cmd);
576         }
577
578         return NULL;
579 }
580
581
582 static char * wpa_cli_dummy_gen(const char *text, int state)
583 {
584         return NULL;
585 }
586
587
588 static char ** wpa_cli_completion(const char *text, int start, int end)
589 {
590         return rl_completion_matches(text, start == 0 ?
591                                      wpa_cli_cmd_gen : wpa_cli_dummy_gen);
592 }
593 #endif /* CONFIG_READLINE */
594
595
596 static void wpa_cli_interactive(void)
597 {
598 #define max_args 10
599         char cmdbuf[256], *cmd, *argv[max_args], *pos;
600         int argc;
601 #ifdef CONFIG_READLINE
602         char *home, *hfile = NULL;
603 #endif /* CONFIG_READLINE */
604
605         printf("\nInteractive mode\n\n");
606
607 #ifdef CONFIG_READLINE
608         rl_attempted_completion_function = wpa_cli_completion;
609         home = getenv("HOME");
610         if (home) {
611                 const char *fname = ".wpa_cli_history";
612                 int hfile_len = strlen(home) + 1 + strlen(fname) + 1;
613                 hfile = malloc(hfile_len);
614                 if (hfile) {
615                         snprintf(hfile, hfile_len, "%s/%s", home, fname);
616                         read_history(hfile);
617                         stifle_history(100);
618                 }
619         }
620 #endif /* CONFIG_READLINE */
621
622         do {
623                 wpa_cli_recv_pending(ctrl_conn, 0);
624 #ifndef CONFIG_NATIVE_WINDOWS
625                 alarm(1);
626 #endif /* CONFIG_NATIVE_WINDOWS */
627 #ifdef CONFIG_READLINE
628                 cmd = readline("> ");
629                 if (cmd && *cmd) {
630                         HIST_ENTRY *h;
631                         while (next_history())
632                                 ;
633                         h = previous_history();
634                         if (h == NULL || strcmp(cmd, h->line) != 0)
635                                 add_history(cmd);
636                         next_history();
637                 }
638 #else /* CONFIG_READLINE */
639                 printf("> ");
640                 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
641 #endif /* CONFIG_READLINE */
642 #ifndef CONFIG_NATIVE_WINDOWS
643                 alarm(0);
644 #endif /* CONFIG_NATIVE_WINDOWS */
645                 if (cmd == NULL)
646                         break;
647                 pos = cmd;
648                 while (*pos != '\0') {
649                         if (*pos == '\n') {
650                                 *pos = '\0';
651                                 break;
652                         }
653                         pos++;
654                 }
655                 argc = 0;
656                 pos = cmd;
657                 for (;;) {
658                         while (*pos == ' ')
659                                 pos++;
660                         if (*pos == '\0')
661                                 break;
662                         argv[argc] = pos;
663                         argc++;
664                         if (argc == max_args)
665                                 break;
666                         while (*pos != '\0' && *pos != ' ')
667                                 pos++;
668                         if (*pos == ' ')
669                                 *pos++ = '\0';
670                 }
671                 if (argc)
672                         wpa_request(ctrl_conn, argc, argv);
673
674                 if (cmd != cmdbuf)
675                         free(cmd);
676         } while (!wpa_cli_quit);
677
678 #ifdef CONFIG_READLINE
679         if (hfile) {
680                 /* Save command history, excluding lines that may contain
681                  * passwords. */
682                 HIST_ENTRY *h;
683                 history_set_pos(0);
684                 h = next_history();
685                 while (h) {
686                         char *p = h->line;
687                         while (*p == ' ' || *p == '\t')
688                                 p++;
689                         if (strncasecmp(p, "pa", 2) == 0 ||
690                             strncasecmp(p, "o", 1) == 0) {
691                                 h = remove_history(where_history());
692                                 if (h) {
693                                         free(h->line);
694                                         free(h->data);
695                                         free(h);
696                                 }
697                                 h = current_history();
698                         } else {
699                                 h = next_history();
700                         }
701                 }
702                 write_history(hfile);
703                 free(hfile);
704         }
705 #endif /* CONFIG_READLINE */
706 }
707
708
709 static void wpa_cli_terminate(int sig)
710 {
711         wpa_cli_close_connection();
712         exit(0);
713 }
714
715
716 #ifndef CONFIG_NATIVE_WINDOWS
717 static void wpa_cli_alarm(int sig)
718 {
719         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
720                 printf("Connection to wpa_supplicant lost - trying to "
721                        "reconnect\n");
722                 wpa_cli_close_connection();
723         }
724         if (!ctrl_conn) {
725                 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
726                 if (ctrl_conn) {
727                         printf("Connection to wpa_supplicant "
728                                "re-established\n");
729                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
730                                 wpa_cli_attached = 1;
731                         } else {
732                                 printf("Warning: Failed to attach to "
733                                        "wpa_supplicant.\n");
734                         }
735                 }
736         }
737         if (ctrl_conn)
738                 wpa_cli_recv_pending(ctrl_conn, 1);
739         alarm(1);
740 }
741 #endif /* CONFIG_NATIVE_WINDOWS */
742
743
744 int main(int argc, char *argv[])
745 {
746         int interactive;
747         int warning_displayed = 0;
748         int c;
749
750 #ifdef CONFIG_NATIVE_WINDOWS
751         WSADATA wsaData;
752         if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
753                 printf("Could not find a usable WinSock.dll\n");
754                 return -1;
755         }
756 #endif /* CONFIG_NATIVE_WINDOWS */
757
758         for (;;) {
759                 c = getopt(argc, argv, "hi:p:v");
760                 if (c < 0)
761                         break;
762                 switch (c) {
763                 case 'h':
764                         usage();
765                         return 0;
766                 case 'v':
767                         printf("%s\n", wpa_cli_version);
768                         return 0;
769                 case 'i':
770                         ctrl_ifname = strdup(optarg);
771                         break;
772                 case 'p':
773                         ctrl_iface_dir = optarg;
774                         break;
775                 default:
776                         usage();
777                         return -1;
778                 }
779         }
780
781         interactive = argc == optind;
782
783         if (interactive)
784                 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
785
786         for (;;) {
787                 if (ctrl_ifname == NULL) {
788                         struct dirent *dent;
789                         DIR *dir = opendir(ctrl_iface_dir);
790                         if (dir) {
791                                 while ((dent = readdir(dir))) {
792                                         if (strcmp(dent->d_name, ".") == 0 ||
793                                             strcmp(dent->d_name, "..") == 0)
794                                                 continue;
795                                         printf("Selected interface '%s'\n",
796                                                dent->d_name);
797                                         ctrl_ifname = strdup(dent->d_name);
798                                         break;
799                                 }
800                                 closedir(dir);
801                         }
802                 }
803                 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
804                 if (ctrl_conn) {
805                         if (warning_displayed)
806                                 printf("Connection established.\n");
807                         break;
808                 }
809
810                 if (!interactive) {
811                         perror("Failed to connect to wpa_supplicant - "
812                                "wpa_ctrl_open");
813                         return -1;
814                 }
815
816                 if (!warning_displayed) {
817                         printf("Could not connect to wpa_supplicant - "
818                                "re-trying\n");
819                         warning_displayed = 1;
820                 }
821                 sleep(1);
822                 continue;
823         }
824
825         signal(SIGINT, wpa_cli_terminate);
826         signal(SIGTERM, wpa_cli_terminate);
827 #ifndef CONFIG_NATIVE_WINDOWS
828         signal(SIGALRM, wpa_cli_alarm);
829 #endif /* CONFIG_NATIVE_WINDOWS */
830
831         if (interactive) {
832                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
833                         wpa_cli_attached = 1;
834                 } else {
835                         printf("Warning: Failed to attach to "
836                                "wpa_supplicant.\n");
837                 }
838                 wpa_cli_interactive();
839         } else
840                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
841
842         free(ctrl_ifname);
843         wpa_cli_close_connection();
844
845 #ifdef CONFIG_NATIVE_WINDOWS
846         WSACleanup();
847 #endif /* CONFIG_NATIVE_WINDOWS */
848
849         return 0;
850 }