Teaching an old dog new tricks
No Matches
dlg_query.c File Reference

Routines for querying an external address book. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "editor/lib.h"
#include "history/lib.h"
#include "key/lib.h"
#include "menu/lib.h"
#include "pattern/lib.h"
#include "send/lib.h"
#include "alias.h"
#include "format_flags.h"
#include "functions.h"
#include "globals.h"
#include "gui.h"
#include "mutt_logging.h"
#include "muttlib.h"
+ Include dependency graph for dlg_query.c:

Go to the source code of this file.


bool alias_to_addrlist (struct AddressList *al, struct Alias *alias)
 Turn an Alias into an AddressList.
static const char * query_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the query menu - Implements format_t -.
static void query_make_entry (struct Menu *menu, char *buf, size_t buflen, int line)
 Format a menu item for the query list - Implements Menu::make_entry() -.
static int query_tag (struct Menu *menu, int sel, int act)
 Tag an entry in the Query Menu - Implements Menu::tag() -.
int query_run (const char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
 Run an external program to find Addresses.
static int query_window_observer (struct NotifyCallback *nc)
 Notification that a Window has changed - Implements observer_t -.
static struct MuttWindowquery_dialog_new (struct AliasMenuData *mdata, const char *query)
 Create an Query Selection Dialog.
static bool dlg_query (struct Buffer *buf, struct AliasMenuData *mdata)
 Get the user to enter an Address Query -.
int query_complete (struct Buffer *buf, struct ConfigSubset *sub)
 Perform auto-complete using an Address Query.
void query_index (struct Mailbox *m, struct ConfigSubset *sub)
 Perform an Alias Query and display the results.


static const struct Mapping QueryHelp []
 Help Bar for the Address Query dialog.

Detailed Description

Routines for querying an external address book.

  • Michael R. Elkins
  • Pietro Cerutti
  • Richard Russon

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, see

Definition in file dlg_query.c.

Function Documentation

◆ alias_to_addrlist()

bool alias_to_addrlist ( struct AddressList *  al,
struct Alias alias 

Turn an Alias into an AddressList.

alAddressList to fill (must be empty)
aliasAlias to use
Return values

Definition at line 120 of file dlg_query.c.

122 if (!al || !TAILQ_EMPTY(al) || !alias)
123 return false;
125 mutt_addrlist_copy(al, &alias->addr, false);
126 if (!TAILQ_EMPTY(al))
127 {
128 struct Address *first = TAILQ_FIRST(al);
129 struct Address *second = TAILQ_NEXT(first, entries);
130 if (!second && !first->personal)
131 {
132 first->personal = buf_new(alias->name);
133 }
135 mutt_addrlist_to_intl(al, NULL);
136 }
138 return true;
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:762
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1294
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:316
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
#define TAILQ_EMPTY(head)
Definition: queue.h:721
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
char * name
Short name.
Definition: alias.h:35
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_run()

int query_run ( const char *  s,
bool  verbose,
struct AliasList *  al,
const struct ConfigSubset sub 

Run an external program to find Addresses.

sString to match
verboseIf true, print progress messages
alAlias list to fill
subConfig items
Return values

Definition at line 260 of file dlg_query.c.

262 FILE *fp = NULL;
263 char *buf = NULL;
264 size_t buflen;
265 char *msg = NULL;
266 size_t msglen = 0;
267 char *p = NULL;
268 struct Buffer *cmd = buf_pool_get();
270 const char *const c_query_command = cs_subset_string(sub, "query_command");
271 buf_file_expand_fmt_quote(cmd, c_query_command, s);
273 pid_t pid = filter_create(buf_string(cmd), NULL, &fp, NULL, EnvList);
274 if (pid < 0)
275 {
276 mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", buf_string(cmd));
277 buf_pool_release(&cmd);
278 return -1;
279 }
280 buf_pool_release(&cmd);
282 if (verbose)
283 mutt_message(_("Waiting for response..."));
285 /* The query protocol first reads one NL-terminated line. If an error
286 * occurs, this is assumed to be an error message. Otherwise it's ignored. */
287 msg = mutt_file_read_line(msg, &msglen, fp, NULL, MUTT_RL_NO_FLAGS);
288 while ((buf = mutt_file_read_line(buf, &buflen, fp, NULL, MUTT_RL_NO_FLAGS)))
289 {
290 p = strtok(buf, "\t\n");
291 if (p)
292 {
293 struct Alias *alias = alias_new();
295 mutt_addrlist_parse(&alias->addr, p);
296 p = strtok(NULL, "\t\n");
297 if (p)
298 {
299 alias->name = mutt_str_dup(p);
300 p = strtok(NULL, "\t\n");
301 alias->comment = mutt_str_dup(p);
302 }
303 TAILQ_INSERT_TAIL(al, alias, entries);
304 }
305 }
306 FREE(&buf);
307 mutt_file_fclose(&fp);
308 if (filter_wait(pid))
309 {
310 mutt_debug(LL_DEBUG1, "Error: %s\n", msg);
311 if (verbose)
312 mutt_error("%s", msg);
313 }
314 else
315 {
316 if (verbose)
317 mutt_message("%s", msg);
318 }
319 FREE(&msg);
321 return 0;
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:478
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:630
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:763
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
void buf_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1497
No flags are set.
Definition: file.h:39
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:218
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition: filter.c:207
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:85
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
Log at debug level 1.
Definition: logging2.h:43
#define FREE(x)
Definition: memory.h:45
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
A shortcut for an email address or addresses.
Definition: alias.h:34
char * comment
Free-form comment string.
Definition: alias.h:37
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_dialog_new()

static struct MuttWindow * query_dialog_new ( struct AliasMenuData mdata,
const char *  query 

Create an Query Selection Dialog.

mdataMenu data holding Aliases
queryInitial query string
Return values
ptrNew Dialog

Definition at line 356 of file dlg_query.c.

360 struct Menu *menu = dlg->wdata;
363 menu->tag = query_tag;
364 menu->max = ARRAY_SIZE(&mdata->ava);
365 mdata->title = mutt_str_dup(_("Query"));
366 menu->mdata = mdata;
367 menu->mdata_free = NULL; // Menu doesn't own the data
369 struct MuttWindow *win_menu = menu->win;
371 // Override the Simple Dialog's recalc()
372 win_menu->recalc = alias_recalc;
374 char title[256] = { 0 };
375 snprintf(title, sizeof(title), "%s: %s", mdata->title, query);
376 struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
377 sbar_set_title(sbar, title);
379 // NT_COLOR is handled by the SimpleDialog
383 return dlg;
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
static const struct Mapping QueryHelp[]
Help Bar for the Address Query dialog.
Definition: dlg_query.c:100
static void query_make_entry(struct Menu *menu, char *buf, size_t buflen, int line)
Format a menu item for the query list - Implements Menu::make_entry() -.
Definition: dlg_query.c:224
static int query_tag(struct Menu *menu, int sel, int act)
Tag an entry in the Query Menu - Implements Menu::tag() -.
Definition: dlg_query.c:239
static int query_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: dlg_query.c:327
int alias_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: gui.c:43
int alias_recalc(struct MuttWindow *win)
Recalculate the display of the Alias Window - Implements MuttWindow::recalc() -.
Definition: gui.c:89
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:132
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:191
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:533
Query Dialog, dlg_query()
Definition: mutt_window.h:90
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:57
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:43
void sbar_set_title(struct MuttWindow *win, const char *title)
Set the title for the Simple Bar.
Definition: sbar.c:227
char * title
Title for the status bar.
Definition: gui.h:60
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
Definition: lib.h:70
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:77
void(* make_entry)(struct Menu *menu, char *buf, size_t buflen, int line)
Definition: lib.h:96
void(* mdata_free)(struct Menu *menu, void **ptr)
Definition: lib.h:151
int(* tag)(struct Menu *menu, int sel, int act)
Definition: lib.h:121
void * mdata
Private data.
Definition: lib.h:137
int max
Number of entries in the menu.
Definition: lib.h:72
void * wdata
Private data.
Definition: mutt_window.h:145
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:173
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
Select from results of external query.
Definition: type.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_complete()

int query_complete ( struct Buffer buf,
struct ConfigSubset sub 

Perform auto-complete using an Address Query.

bufBuffer for completion
subConfig item
Return values

Definition at line 456 of file dlg_query.c.

458 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
459 mdata.search_state = search_state_new();
461 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
462 const char *const c_query_command = cs_subset_string(sub, "query_command");
463 if (!c_query_command)
464 {
465 mutt_warning(_("Query command not defined"));
466 goto done;
467 }
469 query_run(buf_string(buf), true, &al, sub);
470 if (TAILQ_EMPTY(&al))
471 goto done;
473 = &al;
475 struct Alias *a_first = TAILQ_FIRST(&al);
476 if (!TAILQ_NEXT(a_first, entries)) // only one response?
477 {
478 struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
479 if (alias_to_addrlist(&addr, a_first))
480 {
482 buf_reset(buf);
483 mutt_addrlist_write(&addr, buf, false);
484 mutt_addrlist_clear(&addr);
486 }
487 goto done;
488 }
490 struct Alias *np = NULL;
491 TAILQ_FOREACH(np,, entries)
492 {
493 alias_array_alias_add(&mdata.ava, np);
494 }
496 /* multiple results, choose from query menu */
497 if (!dlg_query(buf, &mdata))
498 goto done;
500 buf_reset(buf);
501 buf_alloc(buf, 8192);
502 bool first = true;
503 struct AliasView *avp = NULL;
504 ARRAY_FOREACH(avp, &mdata.ava)
505 {
506 if (!avp->is_tagged)
507 continue;
509 if (!first)
510 {
511 buf_addstr(buf, ", ");
512 }
514 first = false;
515 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
516 if (alias_to_addrlist(&al_copy, avp->alias))
517 {
518 mutt_addrlist_to_local(&al_copy);
519 mutt_addrlist_write(&al_copy, buf, false);
520 mutt_addrlist_clear(&al_copy);
521 }
522 }
525 ARRAY_FREE(&mdata.ava);
526 FREE(&mdata.title);
527 FREE(&mdata.limit);
529 aliaslist_free(&al);
530 return 0;
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1461
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1379
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1207
void aliaslist_free(struct AliasList *al)
Free a List of Aliases.
Definition: alias.c:662
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:47
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:203
Static initializer for arrays.
Definition: array.h:57
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:349
int query_run(const char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition: dlg_query.c:260
bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlg_query.c:120
static bool dlg_query(struct Buffer *buf, struct AliasMenuData *mdata)
Get the user to enter an Address Query -.
Definition: dlg_query.c:397
#define mutt_warning(...)
Definition: logging2.h:90
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
Definition: queue.h:637
void search_state_free(struct SearchState **ptr)
Free a SearchState.
Definition: search_state.c:50
struct SearchState * search_state_new(void)
Create a new SearchState.
Definition: search_state.c:38
AliasView array wrapper with Pattern information -.
Definition: gui.h:52
char * limit
Limit being used.
Definition: gui.h:58
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:53
struct SearchState * search_state
State of the current search.
Definition: gui.h:61
struct AliasList * al
Alias data.
Definition: gui.h:54
struct ConfigSubset * sub
Config items.
Definition: gui.h:55
GUI data wrapping an Alias.
Definition: gui.h:36
struct Alias * alias
Definition: gui.h:44
bool is_tagged
Is it tagged?
Definition: gui.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_index()

void query_index ( struct Mailbox m,
struct ConfigSubset sub 

Perform an Alias Query and display the results.

subConfig item

Definition at line 538 of file dlg_query.c.

540 const char *const c_query_command = cs_subset_string(sub, "query_command");
541 if (!c_query_command)
542 {
543 mutt_warning(_("Query command not defined"));
544 return;
545 }
547 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
548 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
549 = &al;
550 mdata.search_state = search_state_new();
552 struct Buffer *buf = buf_pool_get();
553 if ((mw_get_field(_("Query: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
554 buf_is_empty(buf))
555 {
556 goto done;
557 }
559 query_run(buf_string(buf), false, &al, sub);
560 if (TAILQ_EMPTY(&al))
561 goto done;
563 struct Alias *np = NULL;
564 TAILQ_FOREACH(np,, entries)
565 {
566 alias_array_alias_add(&mdata.ava, np);
567 }
569 if (!dlg_query(buf, &mdata))
570 goto done;
572 // Prepare the "To:" field of a new email
573 struct Email *e = email_new();
574 e->env = mutt_env_new();
576 struct AliasView *avp = NULL;
577 ARRAY_FOREACH(avp, &mdata.ava)
578 {
579 if (!avp->is_tagged)
580 continue;
582 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
583 if (alias_to_addrlist(&al_copy, avp->alias))
584 {
585 mutt_addrlist_copy(&e->env->to, &al_copy, false);
586 mutt_addrlist_clear(&al_copy);
587 }
588 }
590 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
593 ARRAY_FREE(&mdata.ava);
594 FREE(&mdata.title);
595 FREE(&mdata.limit);
597 aliaslist_free(&al);
598 buf_pool_release(&buf);
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:275
Miscellaneous strings.
Definition: lib.h:54
No flags are set.
Definition: mutt.h:55
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2127
Allow the user to edit the To field.
Definition: send.h:54
The envelope/body of an email.
Definition: email.h:37
struct Envelope * env
Envelope information.
Definition: email.h:66
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ QueryHelp

const struct Mapping QueryHelp[]
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("Mail"), OP_MAIL },
{ N_("New Query"), OP_QUERY },
{ N_("Make Alias"), OP_CREATE_ALIAS },
{ N_("Sort"), OP_SORT },
{ N_("Rev-Sort"), OP_SORT_REVERSE },
{ N_("Search"), OP_SEARCH },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
#define N_(a)
Definition: message.h:32

Help Bar for the Address Query dialog.

Definition at line 100 of file dlg_query.c.