Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multipathd: replace libreadline with fgets() #41

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 0 additions & 107 deletions multipathd/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "parser.h"
#include "util.h"
#include "version.h"
#include <readline/readline.h>

#include "mpath_cmd.h"
#include "cli.h"
Expand Down Expand Up @@ -453,109 +452,3 @@ void cli_exit(void)
free_keys(keys);
keys = NULL;
}

static int
key_match_fingerprint (struct key * kw, uint64_t fp)
{
if (!fp)
return 0;

return ((fp & kw->code) == kw->code);
}

/*
* This is the readline completion handler
*/
char *
key_generator (const char * str, int state)
{
static int index, len, has_param;
static uint64_t rlfp;
struct key * kw;
int i;
struct handler *h;
vector v = NULL;

if (!state) {
index = 0;
has_param = 0;
rlfp = 0;
len = strlen(str);
int r = get_cmdvec(rl_line_buffer, &v);
/*
* If a word completion is in progress, we don't want
* to take an exact keyword match in the fingerprint.
* For ex "show map[tab]" would validate "map" and discard
* "maps" as a valid candidate.
*/
if (v && len)
vector_del_slot(v, VECTOR_SIZE(v) - 1);
/*
* Clean up the mess if we dropped the last slot of a 1-slot
* vector
*/
if (v && !VECTOR_SIZE(v)) {
vector_free(v);
v = NULL;
}
/*
* If last keyword takes a param, don't even try to guess
*/
if (r == EINVAL) {
has_param = 1;
return (strdup("(value)"));
}
/*
* Compute a command fingerprint to find out possible completions.
* Once done, the vector is useless. Free it.
*/
if (v) {
rlfp = fingerprint(v);
free_keys(v);
}
}
/*
* No more completions for parameter placeholder.
* Brave souls might try to add parameter completion by walking paths and
* multipaths vectors.
*/
if (has_param)
return ((char *)NULL);
/*
* Loop through keywords for completion candidates
*/
vector_foreach_slot_after (keys, kw, index) {
if (!strncmp(kw->str, str, len)) {
/*
* Discard keywords already in the command line
*/
if (key_match_fingerprint(kw, rlfp)) {
struct key * curkw = find_key(str);
if (!curkw || (curkw != kw))
continue;
}
/*
* Discard keywords making syntax errors.
*
* nfp is the candidate fingerprint we try to
* validate against all known command fingerprints.
*/
uint64_t nfp = rlfp | kw->code;
vector_foreach_slot(handlers, h, i) {
if (!rlfp || ((h->fingerprint & nfp) == nfp)) {
/*
* At least one full command is
* possible with this keyword :
* Consider it validated
*/
index++;
return (strdup(kw->str));
}
}
}
}
/*
* No more candidates
*/
return ((char *)NULL);
}
23 changes: 10 additions & 13 deletions multipathd/uxclnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <poll.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <ctype.h>

#include "mpath_cmd.h"
#include "uxsock.h"
Expand Down Expand Up @@ -70,20 +69,20 @@ static int need_quit(char *str, size_t len)
*/
static void process(int fd, unsigned int timeout)
{
char *line;
char line[256];
char *reply;
unsigned int i;
int ret;
char prompt[] = "multipathd> ";

cli_init();
rl_readline_name = "multipathd";
rl_completion_entry_function = key_generator;
while ((line = readline("multipathd> "))) {
for (i = 0; i < strlen(prompt); i++)
fputc(prompt[i], stdout);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just use fputs()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because fputs() always attaches a newline, and we want to display a prompt (ie without a newline).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because fputs() always attaches a newline

puts() does this but fputs() does not.

while (fgets(line, 256, stdin)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd need some error handling here, especially for overflow, and we should strip training newline. I'd prefer using getline(), actually.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sure. The really was a quick-and-dirty hack, and fgets() was the first function which came to my mind. getline() is fine, too.

size_t llen = strlen(line);

if (!llen) {
free(line);
if (!llen)
continue;
}

if (need_quit(line, llen))
break;
Expand All @@ -94,11 +93,9 @@ static void process(int fd, unsigned int timeout)

print_reply(reply);

if (line && *line)
add_history(line);

free(line);
free(reply);
for (i = 0; i < strlen(prompt); i++)
fputc(prompt[i], stdout);
}
}

Expand Down