NeoMutt  2021-02-05-329-g9e03b7
Teaching an old dog new tricks
DOXYGEN
init.c File Reference

Config/command parsing. More...

#include "config.h"
#include <ctype.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "init.h"
#include "history/lib.h"
#include "notmuch/lib.h"
#include "command_parse.h"
#include "context.h"
#include "functions.h"
#include "keymap.h"
#include "mutt_commands.h"
#include "mutt_globals.h"
#include "mutt_lua.h"
#include "menu/lib.h"
#include "muttlib.h"
#include "myvar.h"
#include "options.h"
#include "protos.h"
#include "sort.h"
#include "sidebar/lib.h"
#include "compmbox/lib.h"
#include "imap/lib.h"
+ Include dependency graph for init.c:

Go to the source code of this file.

Functions

static void matches_ensure_morespace (int current)
 Allocate more space for auto-completion. More...
 
static void candidate (char *user, const char *src, char *dest, size_t dlen)
 helper function for completion More...
 
static int complete_all_nm_tags (const char *pt)
 Pass a list of Notmuch tags to the completion code. More...
 
static int execute_commands (struct ListHead *p)
 Execute a set of NeoMutt commands. More...
 
static char * find_cfg (const char *home, const char *xdg_cfg_home)
 Find a config file. More...
 
static char * getmailname (void)
 Try to retrieve the FQDN from mailname files. More...
 
static bool get_hostname (struct ConfigSet *cs)
 Find the Fully-Qualified Domain Name. More...
 
int mutt_extract_token (struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
 Extract one token from a string. More...
 
void mutt_opts_free (void)
 clean up before quitting More...
 
HookFlags mutt_get_hook_type (const char *name)
 Find a hook by name. More...
 
int mutt_init (struct ConfigSet *cs, bool skip_sys_rc, struct ListHead *commands)
 Initialise NeoMutt. More...
 
enum CommandResult mutt_parse_rc_buffer (struct Buffer *line, struct Buffer *token, struct Buffer *err)
 Parse a line of user config. More...
 
enum CommandResult mutt_parse_rc_line (const char *line, struct Buffer *err)
 Parse a line of user config. More...
 
int mutt_query_variables (struct ListHead *queries, bool show_docs)
 Implement the -Q command line flag. More...
 
int mutt_command_complete (char *buf, size_t buflen, int pos, int numtabs)
 Complete a command name. More...
 
int mutt_label_complete (char *buf, size_t buflen, int numtabs)
 Complete a label name. More...
 
bool mutt_nm_query_complete (char *buf, size_t buflen, int pos, int numtabs)
 Complete to the nearest notmuch tag. More...
 
bool mutt_nm_tag_complete (char *buf, size_t buflen, int numtabs)
 Complete to the nearest notmuch tag. More...
 
int mutt_var_value_complete (char *buf, size_t buflen, int pos)
 Complete a variable/value. More...
 

Variables

static char UserTyped [1024] = { 0 }
 
static int NumMatched = 0
 
static char Completed [256] = { 0 }
 
static const char ** Matches
 
static int MatchesListsize = 512
 
static char ** nm_tags
 

Detailed Description

Config/command parsing.

Authors
  • Michael R. Elkins
  • Pietro Cerutti

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 http://www.gnu.org/licenses/.

Definition in file init.c.

Function Documentation

◆ matches_ensure_morespace()

static void matches_ensure_morespace ( int  current)
static

Allocate more space for auto-completion.

Parameters
currentCurrent allocation

Definition at line 96 of file init.c.

97 {
98  if (current <= (MatchesListsize - 2))
99  return;
100 
101  int base_space = 512; // Enough space for all of the config items
102  int extra_space = MatchesListsize - base_space;
103  extra_space *= 2;
104  const int space = base_space + extra_space;
105  mutt_mem_realloc(&Matches, space * sizeof(char *));
106  memset(&Matches[current + 1], 0, space - current);
107  MatchesListsize = space;
108 }
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
static int MatchesListsize
Definition: init.c:85
static const char ** Matches
Definition: init.c:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ candidate()

static void candidate ( char *  user,
const char *  src,
char *  dest,
size_t  dlen 
)
static

helper function for completion

Parameters
userUser entered data for completion
srcCandidate for completion
destCompletion result gets here
dlenLength of dest buffer

Changes the dest buffer if necessary/possible to aid completion.

Definition at line 119 of file init.c.

120 {
121  if (!dest || !user || !src)
122  return;
123 
124  if (strstr(src, user) != src)
125  return;
126 
128  Matches[NumMatched++] = src;
129  if (dest[0] == '\0')
130  mutt_str_copy(dest, src, dlen);
131  else
132  {
133  int l;
134  for (l = 0; src[l] && src[l] == dest[l]; l++)
135  ; // do nothing
136 
137  dest[l] = '\0';
138  }
139 }
static int NumMatched
Definition: init.c:81
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:96
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
static const char ** Matches
Definition: init.c:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ complete_all_nm_tags()

static int complete_all_nm_tags ( const char *  pt)
static

Pass a list of Notmuch tags to the completion code.

Parameters
ptList of all Notmuch tags
Return values
0Success
-1Error

Definition at line 148 of file init.c.

149 {
150  struct Mailbox *m = ctx_mailbox(Context);
151  int tag_count_1 = 0;
152  int tag_count_2 = 0;
153 
154  NumMatched = 0;
155  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
156  memset(Matches, 0, MatchesListsize);
157  memset(Completed, 0, sizeof(Completed));
158 
159  nm_db_longrun_init(m, false);
160 
161  /* Work out how many tags there are. */
162  if (nm_get_all_tags(m, NULL, &tag_count_1) || (tag_count_1 == 0))
163  goto done;
164 
165  /* Free the old list, if any. */
166  if (nm_tags)
167  {
168  for (int i = 0; nm_tags[i]; i++)
169  FREE(&nm_tags[i]);
170  FREE(&nm_tags);
171  }
172  /* Allocate a new list, with sentinel. */
173  nm_tags = mutt_mem_malloc((tag_count_1 + 1) * sizeof(char *));
174  nm_tags[tag_count_1] = NULL;
175 
176  /* Get all the tags. */
177  if (nm_get_all_tags(m, nm_tags, &tag_count_2) || (tag_count_1 != tag_count_2))
178  {
179  FREE(&nm_tags);
180  nm_tags = NULL;
182  return -1;
183  }
184 
185  /* Put them into the completion machinery. */
186  for (int num = 0; num < tag_count_1; num++)
187  {
188  candidate(UserTyped, nm_tags[num], Completed, sizeof(Completed));
189  }
190 
193 
194 done:
196  return 0;
197 }
The "current" mailbox.
Definition: context.h:37
struct Mailbox * ctx_mailbox(struct Context *ctx)
wrapper to get the mailbox in a Context, or NULL
Definition: context.c:440
static int NumMatched
Definition: init.c:81
static char ** nm_tags
Definition: init.c:89
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:314
static char Completed[256]
Definition: init.c:82
static int MatchesListsize
Definition: init.c:85
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:96
A mailbox.
Definition: mailbox.h:81
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: db.c:329
int nm_get_all_tags(struct Mailbox *m, char **tag_list, int *tag_count)
Fill a list with all notmuch tags.
Definition: notmuch.c:2037
static char UserTyped[1024]
Definition: init.c:79
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
static const char ** Matches
Definition: init.c:83
#define FREE(x)
Definition: memory.h:40
static void candidate(char *user, const char *src, char *dest, size_t dlen)
helper function for completion
Definition: init.c:119
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ execute_commands()

static int execute_commands ( struct ListHead *  p)
static

Execute a set of NeoMutt commands.

Parameters
pList of command strings
Return values
0Success, all the commands succeeded
-1Error

Definition at line 206 of file init.c.

207 {
208  int rc = 0;
209  struct Buffer *err = mutt_buffer_pool_get();
210 
211  struct ListNode *np = NULL;
212  STAILQ_FOREACH(np, p, entries)
213  {
214  enum CommandResult rc2 = mutt_parse_rc_line(np->data, err);
215  if (rc2 == MUTT_CMD_ERROR)
216  mutt_error(_("Error in command line: %s"), mutt_buffer_string(err));
217  else if (rc2 == MUTT_CMD_WARNING)
218  mutt_warning(_("Warning in command line: %s"), mutt_buffer_string(err));
219 
220  if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
221  {
223  return -1;
224  }
225  }
227 
228  return rc;
229 }
#define mutt_warning(...)
Definition: logging.h:82
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:1038
#define _(a)
Definition: message.h:28
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * data
String.
Definition: list.h:36
Warning: Help given to the user.
Definition: mutt_commands.h:37
#define mutt_error(...)
Definition: logging.h:84
A List node for strings.
Definition: list.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_cfg()

static char* find_cfg ( const char *  home,
const char *  xdg_cfg_home 
)
static

Find a config file.

Parameters
homeUser's home directory
xdg_cfg_homeXDG home directory
Return values
ptrSuccess, first matching directory
NULLError, no matching directories

Definition at line 238 of file init.c.

239 {
240  const char *names[] = {
241  "neomuttrc",
242  "muttrc",
243  NULL,
244  };
245 
246  const char *locations[][2] = {
247  { xdg_cfg_home, "neomutt/" },
248  { xdg_cfg_home, "mutt/" },
249  { home, ".neomutt/" },
250  { home, ".mutt/" },
251  { home, "." },
252  { NULL, NULL },
253  };
254 
255  for (int i = 0; locations[i][0] || locations[i][1]; i++)
256  {
257  if (!locations[i][0])
258  continue;
259 
260  for (int j = 0; names[j]; j++)
261  {
262  char buf[256];
263 
264  snprintf(buf, sizeof(buf), "%s/%s%s", locations[i][0], locations[i][1], names[j]);
265  if (access(buf, F_OK) == 0)
266  return mutt_str_dup(buf);
267  }
268  }
269 
270  return NULL;
271 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getmailname()

static char* getmailname ( void  )
static

Try to retrieve the FQDN from mailname files.

Return values
ptrHeap allocated string with the FQDN
NULLNo valid mailname file could be read

Definition at line 279 of file init.c.

280 {
281  char *mailname = NULL;
282  static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
283 
284  for (size_t i = 0; i < mutt_array_size(mn_files); i++)
285  {
286  FILE *fp = mutt_file_fopen(mn_files[i], "r");
287  if (!fp)
288  continue;
289 
290  size_t len = 0;
291  mailname = mutt_file_read_line(NULL, &len, fp, NULL, MUTT_RL_NO_FLAGS);
292  mutt_file_fclose(&fp);
293  if (mailname && *mailname)
294  break;
295 
296  FREE(&mailname);
297  }
298 
299  return mailname;
300 }
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:667
#define mutt_array_size(x)
Definition: memory.h:33
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
#define FREE(x)
Definition: memory.h:40
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_hostname()

static bool get_hostname ( struct ConfigSet cs)
static

Find the Fully-Qualified Domain Name.

Return values
trueSuccess
falseError, failed to find any name

Use several methods to try to find the Fully-Qualified domain name of this host. If the user has already configured a hostname, this function will use it.

Definition at line 311 of file init.c.

312 {
313  const char *short_host = NULL;
314  struct utsname utsname;
315 
316  const char *const c_hostname = cs_subset_string(NeoMutt->sub, "hostname");
317  if (c_hostname)
318  {
319  short_host = c_hostname;
320  }
321  else
322  {
323  /* The call to uname() shouldn't fail, but if it does, the system is horribly
324  * broken, and the system's networking configuration is in an unreliable
325  * state. We should bail. */
326  if ((uname(&utsname)) == -1)
327  {
328  mutt_perror(_("unable to determine nodename via uname()"));
329  return false; // TEST09: can't test
330  }
331 
332  short_host = utsname.nodename;
333  }
334 
335  /* some systems report the FQDN instead of just the hostname */
336  char *dot = strchr(short_host, '.');
337  if (dot)
338  ShortHostname = mutt_strn_dup(short_host, dot - short_host);
339  else
340  ShortHostname = mutt_str_dup(short_host);
341 
342  // All the code paths from here alloc memory for the fqdn
343  char *fqdn = mutt_str_dup(c_hostname);
344  if (!fqdn)
345  {
346  /* now get FQDN. Use configured domain first, DNS next, then uname */
347 #ifdef DOMAIN
348  /* we have a compile-time domain name, use that for `$hostname` */
350  sprintf((char *) fqdn, "%s.%s", NONULL(ShortHostname), DOMAIN);
351 #else
352  fqdn = getmailname();
353  if (!fqdn)
354  {
355  struct Buffer *domain = mutt_buffer_pool_get();
356  if (getdnsdomainname(domain) == 0)
357  {
359  sprintf((char *) fqdn, "%s.%s", NONULL(ShortHostname), mutt_buffer_string(domain));
360  }
361  else
362  {
363  /* DNS failed, use the nodename. Whether or not the nodename had a '.'
364  * in it, we can use the nodename as the FQDN. On hosts where DNS is
365  * not being used, e.g. small network that relies on hosts files, a
366  * short host name is all that is required for SMTP to work correctly.
367  * It could be wrong, but we've done the best we can, at this point the
368  * onus is on the user to provide the correct hostname if the nodename
369  * won't work in their network. */
370  fqdn = mutt_str_dup(utsname.nodename);
371  }
372  mutt_buffer_pool_release(&domain);
373  }
374 #endif
375  }
376 
377  if (fqdn)
378  {
379  cs_str_initial_set(cs, "hostname", fqdn, NULL);
380  cs_str_reset(cs, "hostname", NULL);
381  FREE(&fqdn);
382  }
383 
384  return true;
385 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
static char * getmailname(void)
Try to retrieve the FQDN from mailname files.
Definition: init.c:279
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
int cs_str_initial_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:458
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:295
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
int getdnsdomainname(struct Buffer *result)
Lookup the host&#39;s name using DNS.
Definition: getdomain.c:118
#define FREE(x)
Definition: memory.h:40
int cs_str_reset(const struct ConfigSet *cs, const char *name, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:393
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_extract_token()

int mutt_extract_token ( struct Buffer dest,
struct Buffer tok,
TokenFlags  flags 
)

Extract one token from a string.

Parameters
destBuffer for the result
tokBuffer containing tokens
flagsFlags, see TokenFlags
Return values
0Success
-1Error

Definition at line 395 of file init.c.

396 {
397  if (!dest || !tok)
398  return -1;
399 
400  char ch;
401  char qc = '\0'; /* quote char */
402  char *pc = NULL;
403 
404  /* Some callers used to rely on the (bad) assumption that dest->data would be
405  * non-NULL after calling this function. Perhaps I've missed a few cases, or
406  * a future caller might make the same mistake. */
407  if (!dest->data)
408  mutt_buffer_alloc(dest, 256);
409 
410  mutt_buffer_reset(dest);
411 
412  SKIPWS(tok->dptr);
413  while ((ch = *tok->dptr))
414  {
415  if (qc == '\0')
416  {
417  if ((IS_SPACE(ch) && !(flags & MUTT_TOKEN_SPACE)) ||
418  ((ch == '#') && !(flags & MUTT_TOKEN_COMMENT)) ||
419  ((ch == '+') && (flags & MUTT_TOKEN_PLUS)) ||
420  ((ch == '-') && (flags & MUTT_TOKEN_MINUS)) ||
421  ((ch == '=') && (flags & MUTT_TOKEN_EQUAL)) ||
422  ((ch == '?') && (flags & MUTT_TOKEN_QUESTION)) ||
423  ((ch == ';') && !(flags & MUTT_TOKEN_SEMICOLON)) ||
424  ((flags & MUTT_TOKEN_PATTERN) && strchr("~%=!|", ch)))
425  {
426  break;
427  }
428  }
429 
430  tok->dptr++;
431 
432  if (ch == qc)
433  qc = 0; /* end of quote */
434  else if (!qc && ((ch == '\'') || (ch == '"')) && !(flags & MUTT_TOKEN_QUOTE))
435  qc = ch;
436  else if ((ch == '\\') && (qc != '\''))
437  {
438  if (tok->dptr[0] == '\0')
439  return -1; /* premature end of token */
440  switch (ch = *tok->dptr++)
441  {
442  case 'c':
443  case 'C':
444  if (tok->dptr[0] == '\0')
445  return -1; /* premature end of token */
446  mutt_buffer_addch(dest, (toupper((unsigned char) tok->dptr[0]) - '@') & 0x7f);
447  tok->dptr++;
448  break;
449  case 'e':
450  mutt_buffer_addch(dest, '\033'); // Escape
451  break;
452  case 'f':
453  mutt_buffer_addch(dest, '\f');
454  break;
455  case 'n':
456  mutt_buffer_addch(dest, '\n');
457  break;
458  case 'r':
459  mutt_buffer_addch(dest, '\r');
460  break;
461  case 't':
462  mutt_buffer_addch(dest, '\t');
463  break;
464  default:
465  if (isdigit((unsigned char) ch) && isdigit((unsigned char) tok->dptr[0]) &&
466  isdigit((unsigned char) tok->dptr[1]))
467  {
468  mutt_buffer_addch(dest, (ch << 6) + (tok->dptr[0] << 3) + tok->dptr[1] - 3504);
469  tok->dptr += 2;
470  }
471  else
472  mutt_buffer_addch(dest, ch);
473  }
474  }
475  else if ((ch == '^') && (flags & MUTT_TOKEN_CONDENSE))
476  {
477  if (tok->dptr[0] == '\0')
478  return -1; /* premature end of token */
479  ch = *tok->dptr++;
480  if (ch == '^')
481  mutt_buffer_addch(dest, ch);
482  else if (ch == '[')
483  mutt_buffer_addch(dest, '\033'); // Escape
484  else if (isalpha((unsigned char) ch))
485  mutt_buffer_addch(dest, toupper((unsigned char) ch) - '@');
486  else
487  {
488  mutt_buffer_addch(dest, '^');
489  mutt_buffer_addch(dest, ch);
490  }
491  }
492  else if ((ch == '`') && (!qc || (qc == '"')))
493  {
494  FILE *fp = NULL;
495  pid_t pid;
496 
497  pc = tok->dptr;
498  do
499  {
500  pc = strpbrk(pc, "\\`");
501  if (pc)
502  {
503  /* skip any quoted chars */
504  if (*pc == '\\')
505  pc += 2;
506  }
507  } while (pc && (pc[0] != '`'));
508  if (!pc)
509  {
510  mutt_debug(LL_DEBUG1, "mismatched backticks\n");
511  return -1;
512  }
513  struct Buffer cmd;
514  mutt_buffer_init(&cmd);
515  *pc = '\0';
516  if (flags & MUTT_TOKEN_BACKTICK_VARS)
517  {
518  /* recursively extract tokens to interpolate variables */
519  mutt_extract_token(&cmd, tok,
520  MUTT_TOKEN_QUOTE | MUTT_TOKEN_SPACE | MUTT_TOKEN_COMMENT |
521  MUTT_TOKEN_SEMICOLON | MUTT_TOKEN_NOSHELL);
522  }
523  else
524  {
525  cmd.data = mutt_str_dup(tok->dptr);
526  }
527  *pc = '`';
528  pid = filter_create(cmd.data, NULL, &fp, NULL);
529  if (pid < 0)
530  {
531  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", cmd.data);
532  FREE(&cmd.data);
533  return -1;
534  }
535  FREE(&cmd.data);
536 
537  tok->dptr = pc + 1;
538 
539  /* read line */
540  struct Buffer expn = mutt_buffer_make(0);
541  expn.data = mutt_file_read_line(NULL, &expn.dsize, fp, NULL, MUTT_RL_NO_FLAGS);
542  mutt_file_fclose(&fp);
543  filter_wait(pid);
544 
545  /* if we got output, make a new string consisting of the shell output
546  * plus whatever else was left on the original line */
547  /* BUT: If this is inside a quoted string, directly add output to
548  * the token */
549  if (expn.data)
550  {
551  if (qc)
552  {
553  mutt_buffer_addstr(dest, expn.data);
554  }
555  else
556  {
557  struct Buffer *copy = mutt_buffer_pool_get();
558  mutt_buffer_fix_dptr(&expn);
559  mutt_buffer_copy(copy, &expn);
560  mutt_buffer_addstr(copy, tok->dptr);
561  mutt_buffer_copy(tok, copy);
562  mutt_buffer_seek(tok, 0);
564  }
565  FREE(&expn.data);
566  }
567  }
568  else if ((ch == '$') && (!qc || (qc == '"')) &&
569  ((tok->dptr[0] == '{') || isalpha((unsigned char) tok->dptr[0])))
570  {
571  const char *env = NULL;
572  char *var = NULL;
573 
574  if (tok->dptr[0] == '{')
575  {
576  pc = strchr(tok->dptr, '}');
577  if (pc)
578  {
579  var = mutt_strn_dup(tok->dptr + 1, pc - (tok->dptr + 1));
580  tok->dptr = pc + 1;
581 
582  if ((flags & MUTT_TOKEN_NOSHELL))
583  {
584  mutt_buffer_addch(dest, ch);
585  mutt_buffer_addch(dest, '{');
586  mutt_buffer_addstr(dest, var);
587  mutt_buffer_addch(dest, '}');
588  FREE(&var);
589  }
590  }
591  }
592  else
593  {
594  for (pc = tok->dptr; isalnum((unsigned char) *pc) || (pc[0] == '_'); pc++)
595  ; // do nothing
596 
597  var = mutt_strn_dup(tok->dptr, pc - tok->dptr);
598  tok->dptr = pc;
599  }
600  if (var)
601  {
602  struct Buffer result;
603  mutt_buffer_init(&result);
604  int rc = cs_subset_str_string_get(NeoMutt->sub, var, &result);
605 
606  if (CSR_RESULT(rc) == CSR_SUCCESS)
607  {
608  mutt_buffer_addstr(dest, result.data);
609  FREE(&result.data);
610  }
611  else if ((env = myvar_get(var)))
612  {
613  mutt_buffer_addstr(dest, env);
614  }
615  else if (!(flags & MUTT_TOKEN_NOSHELL) && (env = mutt_str_getenv(var)))
616  {
617  mutt_buffer_addstr(dest, env);
618  }
619  else
620  {
621  mutt_buffer_addch(dest, ch);
622  mutt_buffer_addstr(dest, var);
623  }
624  FREE(&var);
625  }
626  }
627  else
628  mutt_buffer_addch(dest, ch);
629  }
630  mutt_buffer_addch(dest, 0); /* terminate the string */
631  SKIPWS(tok->dptr);
632  return 0;
633 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:72
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
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:667
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define CSR_RESULT(x)
Definition: set.h:52
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
size_t dsize
Length of data.
Definition: buffer.h:37
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define SKIPWS(ch)
Definition: string2.h:46
#define MUTT_TOKEN_NOSHELL
Don&#39;t expand environment variables.
Definition: mutt.h:75
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
#define MUTT_TOKEN_QUOTE
Don&#39;t interpret quotes.
Definition: mutt.h:70
#define MUTT_TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: mutt.h:68
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:395
char * dptr
Current read/write position.
Definition: buffer.h:36
#define MUTT_TOKEN_SPACE
Don&#39;t treat whitespace as a term.
Definition: mutt.h:69
char * data
Pointer to data.
Definition: buffer.h:35
#define MUTT_TOKEN_PLUS
Treat &#39;+&#39; as a special.
Definition: mutt.h:77
int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:357
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
const char * myvar_get(const char *var)
Get the value of a "my_" variable.
Definition: myvar.c:73
#define MUTT_TOKEN_SEMICOLON
Don&#39;t treat ; as special.
Definition: mutt.h:73
#define IS_SPACE(ch)
Definition: string2.h:38
Log at debug level 1.
Definition: logging.h:40
#define MUTT_TOKEN_MINUS
Treat &#39;-&#39; as a special.
Definition: mutt.h:78
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
#define MUTT_TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: mutt.h:74
#define FREE(x)
Definition: memory.h:40
#define MUTT_TOKEN_EQUAL
Treat &#39;=&#39; as a special.
Definition: mutt.h:67
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
set current read/write position to offset from beginning
Definition: buffer.c:466
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:71
#define MUTT_TOKEN_QUESTION
Treat &#39;?&#39; as a special.
Definition: mutt.h:76
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
+ Here is the call graph for this function:

◆ mutt_opts_free()

void mutt_opts_free ( void  )

clean up before quitting

Definition at line 638 of file init.c.

639 {
641 
642  alias_shutdown();
643 #ifdef USE_SIDEBAR
644  sb_shutdown();
645 #endif
646 
652 
656 
657  /* Lists of strings */
658  mutt_list_free(&AlternativeOrderList);
659  mutt_list_free(&AutoViewList);
660  mutt_list_free(&HeaderOrderList);
663  mutt_list_free(&MimeLookupList);
664  mutt_list_free(&Muttrc);
666  mutt_list_free(&UserHeader);
667 
669 
671  FREE(&HomeDir);
672  FREE(&LastFolder);
674  FREE(&Username);
675 
677 
679 
680  mutt_hist_free();
681  mutt_keys_free();
682 
685 }
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: globals.c:43
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: globals.c:40
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:328
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: globals.c:41
void mutt_replacelist_free(struct ReplaceList *rl)
Free a ReplaceList object.
Definition: regex.c:448
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
void clear_source_stack(void)
Free memory from the stack used for the souce command.
void alias_shutdown(void)
Clean up the Alias globals.
Definition: alias.c:670
struct ListHead Ignore
List of header patterns to ignore.
Definition: globals.c:35
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:33
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1709
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:37
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:37
void mutt_colors_cleanup(void)
Cleanup all the colours.
Definition: color.c:384
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:51
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:34
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: globals.c:36
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:50
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: globals.c:42
#define FREE(x)
Definition: memory.h:40
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:38
void mutt_commands_free(void)
Free Commands array.
void mutt_grouplist_free(void)
Free GroupList singleton resource.
Definition: group.c:55
WHERE struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:55
void mutt_hist_free(void)
Free all the history lists.
Definition: history.c:441
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:171
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_hook_type()

HookFlags mutt_get_hook_type ( const char *  name)

Find a hook by name.

Parameters
nameName to find
Return values
numHook ID, e.g. MUTT_FOLDER_HOOK
MUTT_HOOK_NO_FLAGSError, no matching hook

Definition at line 693 of file init.c.

694 {
695  struct Command *c = NULL;
696  for (size_t i = 0, size = mutt_commands_array(&c); i < size; i++)
697  {
698  if (((c[i].parse == mutt_parse_hook) || (c[i].parse == mutt_parse_idxfmt_hook)) &&
699  mutt_istr_equal(c[i].name, name))
700  {
701  return c[i].data;
702  }
703  }
704  return MUTT_HOOK_NO_FLAGS;
705 }
intptr_t data
Data or flags to pass to the command.
Definition: mutt_commands.h:59
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;hook&#39; family of commands - Implements Command::parse()
Definition: hook.c:82
A user-callable command.
Definition: mutt_commands.h:45
const char * name
Name of the command.
Definition: mutt_commands.h:47
size_t mutt_commands_array(struct Command **first)
Get Commands array.
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Function to parse a command.
Definition: mutt_commands.h:57
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
enum CommandResult mutt_parse_idxfmt_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;index-format-hook&#39; command - Implements Command::parse()
Definition: hook.c:372
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_init()

int mutt_init ( struct ConfigSet cs,
bool  skip_sys_rc,
struct ListHead *  commands 
)

Initialise NeoMutt.

Parameters
csConfig Set
skip_sys_rcIf true, don't read the system config file
commandsList of config commands to execute
Return values
0Success
1Error

Definition at line 715 of file init.c.

716 {
717  int need_pause = 0;
718  int rc = 1;
719  struct Buffer err = mutt_buffer_make(256);
720  struct Buffer buf = mutt_buffer_make(256);
721 
723  alias_init();
725 #ifdef USE_COMP_MBOX
726  mutt_comp_init();
727 #endif
728 #ifdef USE_IMAP
729  imap_init();
730 #endif
731 #ifdef USE_LUA
732  mutt_lua_init();
733 #endif
736 
737  menu_init();
738 #ifdef USE_SIDEBAR
739  sb_init();
740 #endif
741 #ifdef USE_NOTMUCH
742  nm_init();
743 #endif
744 
745  /* "$spool_file" precedence: config file, environment */
746  const char *p = mutt_str_getenv("MAIL");
747  if (!p)
748  p = mutt_str_getenv("MAILDIR");
749  if (!p)
750  {
751 #ifdef HOMESPOOL
752  mutt_buffer_concat_path(&buf, NONULL(HomeDir), MAILPATH);
753 #else
754  mutt_buffer_concat_path(&buf, MAILPATH, NONULL(Username));
755 #endif
756  p = mutt_buffer_string(&buf);
757  }
758  cs_str_initial_set(cs, "spool_file", p, NULL);
759  cs_str_reset(cs, "spool_file", NULL);
760 
761  p = mutt_str_getenv("REPLYTO");
762  if (p)
763  {
764  struct Buffer token;
765 
766  mutt_buffer_printf(&buf, "Reply-To: %s", p);
767  mutt_buffer_init(&token);
768  parse_my_hdr(&token, &buf, 0, &err); /* adds to UserHeader */
769  FREE(&token.data);
770  }
771 
772  p = mutt_str_getenv("EMAIL");
773  if (p)
774  {
775  cs_str_initial_set(cs, "from", p, NULL);
776  cs_str_reset(cs, "from", NULL);
777  }
778 
779  /* "$mailcap_path" precedence: config file, environment, code */
780  const char *env_mc = mutt_str_getenv("MAILCAPS");
781  if (env_mc)
782  cs_str_string_set(cs, "mailcap_path", env_mc, NULL);
783 
784  /* "$tmpdir" precedence: config file, environment, code */
785  const char *env_tmp = mutt_str_getenv("TMPDIR");
786  if (env_tmp)
787  cs_str_string_set(cs, "tmpdir", env_tmp, NULL);
788 
789  /* "$visual", "$editor" precedence: config file, environment, code */
790  const char *env_ed = mutt_str_getenv("VISUAL");
791  if (!env_ed)
792  env_ed = mutt_str_getenv("EDITOR");
793  if (!env_ed)
794  env_ed = "vi";
795  cs_str_initial_set(cs, "editor", env_ed, NULL);
796 
797  const char *const c_editor = cs_subset_string(NeoMutt->sub, "editor");
798  if (!c_editor)
799  cs_str_reset(cs, "editor", NULL);
800 
801  const char *charset = mutt_ch_get_langinfo_charset();
802  cs_str_initial_set(cs, "charset", charset, NULL);
803  cs_str_reset(cs, "charset", NULL);
804  mutt_ch_set_charset(charset);
805  FREE(&charset);
806 
807  Matches = mutt_mem_calloc(MatchesListsize, sizeof(char *));
808 
809 #ifdef HAVE_GETSID
810  /* Unset suspend by default if we're the session leader */
811  if (getsid(0) == getpid())
812  cs_subset_str_native_set(NeoMutt->sub, "suspend", false, NULL);
813 #endif
814 
815  /* RFC2368, "4. Unsafe headers"
816  * The creator of a mailto URL can't expect the resolver of a URL to
817  * understand more than the "subject" and "body" headers. Clients that
818  * resolve mailto URLs into mail messages should be able to correctly
819  * create RFC822-compliant mail messages using the "subject" and "body"
820  * headers. */
821  add_to_stailq(&MailToAllow, "body");
822  add_to_stailq(&MailToAllow, "subject");
823  /* Cc, In-Reply-To, and References help with not breaking threading on
824  * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
825  add_to_stailq(&MailToAllow, "cc");
826  add_to_stailq(&MailToAllow, "in-reply-to");
827  add_to_stailq(&MailToAllow, "references");
828 
829  if (STAILQ_EMPTY(&Muttrc))
830  {
831  const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
832 
833  if (!xdg_cfg_home && HomeDir)
834  {
835  mutt_buffer_printf(&buf, "%s/.config", HomeDir);
836  xdg_cfg_home = mutt_buffer_string(&buf);
837  }
838 
839  char *config = find_cfg(HomeDir, xdg_cfg_home);
840  if (config)
841  {
842  mutt_list_insert_tail(&Muttrc, config);
843  }
844  }
845  else
846  {
847  struct ListNode *np = NULL;
848  STAILQ_FOREACH(np, &Muttrc, entries)
849  {
850  mutt_buffer_strcpy(&buf, np->data);
851  FREE(&np->data);
853  np->data = mutt_buffer_strdup(&buf);
854  if (access(np->data, F_OK))
855  {
856  mutt_perror(np->data);
857  goto done; // TEST10: neomutt -F missing
858  }
859  }
860  }
861 
862  if (!STAILQ_EMPTY(&Muttrc))
863  {
864  cs_str_string_set(cs, "alias_file", STAILQ_FIRST(&Muttrc)->data, NULL);
865  }
866 
867  /* Process the global rc file if it exists and the user hasn't explicitly
868  * requested not to via "-n". */
869  if (!skip_sys_rc)
870  {
871  do
872  {
874  break;
875 
876  mutt_buffer_printf(&buf, "%s/neomuttrc", SYSCONFDIR);
877  if (access(mutt_buffer_string(&buf), F_OK) == 0)
878  break;
879 
880  mutt_buffer_printf(&buf, "%s/Muttrc", SYSCONFDIR);
881  if (access(mutt_buffer_string(&buf), F_OK) == 0)
882  break;
883 
884  mutt_buffer_printf(&buf, "%s/neomuttrc", PKGDATADIR);
885  if (access(mutt_buffer_string(&buf), F_OK) == 0)
886  break;
887 
888  mutt_buffer_printf(&buf, "%s/Muttrc", PKGDATADIR);
889  } while (false);
890 
891  if (access(mutt_buffer_string(&buf), F_OK) == 0)
892  {
893  if (source_rc(mutt_buffer_string(&buf), &err) != 0)
894  {
895  mutt_error("%s", err.data);
896  need_pause = 1; // TEST11: neomutt (error in /etc/neomuttrc)
897  }
898  }
899  }
900 
901  /* Read the user's initialization file. */
902  struct ListNode *np = NULL;
903  STAILQ_FOREACH(np, &Muttrc, entries)
904  {
905  if (np->data)
906  {
907  if (source_rc(np->data, &err) != 0)
908  {
909  mutt_error("%s", err.data);
910  need_pause = 1; // TEST12: neomutt (error in ~/.neomuttrc)
911  }
912  }
913  }
914 
915  if (execute_commands(commands) != 0)
916  need_pause = 1; // TEST13: neomutt -e broken
917 
918  if (!get_hostname(cs))
919  goto done;
920 
921  {
922  char name[256] = { 0 };
923  const char *c_real_name = cs_subset_string(NeoMutt->sub, "real_name");
924  if (!c_real_name)
925  {
926  struct passwd *pw = getpwuid(getuid());
927  if (pw)
928  c_real_name = mutt_gecos_name(name, sizeof(name), pw);
929  }
930  cs_str_initial_set(cs, "real_name", c_real_name, NULL);
931  cs_str_reset(cs, "real_name", NULL);
932  }
933 
934  if (need_pause && !OptNoCurses)
935  {
937  if (mutt_any_key_to_continue(NULL) == 'q')
938  goto done; // TEST14: neomutt -e broken (press 'q')
939  }
940 
941  const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
942  mutt_file_mkdir(c_tmpdir, S_IRWXU);
943 
944  mutt_hist_init();
946 
947 #ifdef USE_NOTMUCH
948  const bool c_virtual_spool_file =
949  cs_subset_bool(NeoMutt->sub, "virtual_spool_file");
950  if (c_virtual_spool_file)
951  {
952  /* Find the first virtual folder and open it */
953  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
955  struct MailboxNode *mp = STAILQ_FIRST(&ml);
956  if (mp)
957  cs_str_string_set(cs, "spool_file", mailbox_path(mp->mailbox), NULL);
959  }
960 #endif
961  rc = 0;
962 
963 done:
964  mutt_buffer_dealloc(&err);
965  mutt_buffer_dealloc(&buf);
966  return rc;
967 }
int source_rc(const char *rcfile_path, struct Buffer *err)
Read an initialization file.
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:206
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:67
#define NONULL(x)
Definition: string2.h:37
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:71
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition: charset.c:1007
#define mutt_perror(...)
Definition: logging.h:85
void mutt_lua_init(void)
Setup feature commands.
Definition: mutt_lua.c:452
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:137
int log_disp_terminal(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to the terminal - Implements log_dispatcher_t.
Definition: logging.c:441
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:160
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
static int execute_commands(struct ListHead *p)
Execute a set of NeoMutt commands.
Definition: init.c:206
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:662
void mutt_commands_init(void)
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
int cs_str_string_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: set.c:595
void imap_init(void)
Setup feature commands.
Definition: imap.c:80
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void log_queue_flush(log_dispatcher_t disp)
Replay the log queue.
Definition: logging.c:348
static char * find_cfg(const char *home, const char *xdg_cfg_home)
Find a config file.
Definition: init.c:238
Container for Accounts, Notifications.
Definition: neomutt.h:36
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:991
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:48
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:292
#define MUTT_HASH_STRCASECMP
use strcasecmp() to compare keys
Definition: hash.h:98
void mutt_hist_read_file(void)
Read the History from a file.
Definition: history.c:599
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:877
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int cs_str_initial_set(const struct ConfigSet *cs, const char *name, const char *value, struct Buffer *err)
Set the initial value of a config item.
Definition: set.c:458
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1728
void nm_init(void)
Setup feature commands.
Definition: notmuch.c:94
static int MatchesListsize
Definition: init.c:85
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:45
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:37
char * data
Pointer to data.
Definition: buffer.h:35
static bool get_hostname(struct ConfigSet *cs)
Find the Fully-Qualified Domain Name.
Definition: init.c:311
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:295
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:37
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:182
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition: history.c:468
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
Definition: muttlib.c:1516
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:601
char * data
String.
Definition: list.h:36
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:321
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user&#39;s real name in /etc/passwd.
Definition: muttlib.c:360
#define mutt_error(...)
Definition: logging.h:84
static const char ** Matches
Definition: init.c:83
#define FREE(x)
Definition: memory.h:40
enum CommandResult parse_my_hdr(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the &#39;my_hdr&#39; command - Implements Command::parse()
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
#define STAILQ_EMPTY(head)
Definition: queue.h:345
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
List of Mailboxes.
Definition: mailbox.h:152
int cs_str_reset(const struct ConfigSet *cs, const char *name, struct Buffer *err)
Reset a config item to its initial value.
Definition: set.c:393
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
WHERE struct HashTable * TagFormats
Hash Table of tag-formats (tag -> format string)
Definition: mutt_globals.h:55
A List node for strings.
Definition: list.h:34
XDG system dir: /etc/xdg.
Definition: protos.h:47
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
char * mutt_ch_get_langinfo_charset(void)
Get the user&#39;s choice of character set.
Definition: charset.c:466
#define STAILQ_FIRST(head)
Definition: queue.h:347
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:97
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_rc_buffer()

enum CommandResult mutt_parse_rc_buffer ( struct Buffer line,
struct Buffer token,
struct Buffer err 
)

Parse a line of user config.

Parameters
lineconfig line to read
tokenscratch buffer to be used by parser
errwhere to write error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

The reason for token is to avoid having to allocate and deallocate a lot of memory if we are parsing many lines. the caller can pass in the memory to use, which avoids having to create new space for every call to this function.

Definition at line 980 of file init.c.

982 {
983  if (mutt_buffer_len(line) == 0)
984  return 0;
985 
987 
988  mutt_buffer_reset(err);
989 
990  /* Read from the beginning of line->data */
991  mutt_buffer_seek(line, 0);
992 
993  SKIPWS(line->dptr);
994  while (*line->dptr)
995  {
996  if (*line->dptr == '#')
997  break; /* rest of line is a comment */
998  if (*line->dptr == ';')
999  {
1000  line->dptr++;
1001  continue;
1002  }
1004 
1005  struct Command *cmd = NULL;
1006  size_t size = mutt_commands_array(&cmd);
1007  size_t i;
1008  for (i = 0; i < size; i++)
1009  {
1010  if (mutt_str_equal(token->data, cmd[i].name))
1011  {
1012  rc = cmd[i].parse(token, line, cmd[i].data, err);
1013  if (rc != MUTT_CMD_SUCCESS)
1014  { /* -1 Error, +1 Finish */
1015  goto finish; /* Propagate return code */
1016  }
1017  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) cmd);
1018  break; /* Continue with next command */
1019  }
1020  }
1021  if (i == size)
1022  {
1023  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1024  rc = MUTT_CMD_ERROR;
1025  break; /* Ignore the rest of the line */
1026  }
1027  }
1028 finish:
1029  return rc;
1030 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
intptr_t data
Data or flags to pass to the command.
Definition: mutt_commands.h:59
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
#define _(a)
Definition: message.h:28
A user-callable command.
Definition: mutt_commands.h:45
const char * name
Name of the command.
Definition: mutt_commands.h:47
A Command has been executed, Command.
Definition: notify_type.h:40
size_t mutt_commands_array(struct Command **first)
Get Commands array.
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
enum CommandResult(* parse)(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Function to parse a command.
Definition: mutt_commands.h:57
#define SKIPWS(ch)
Definition: string2.h:46
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:395
char * dptr
Current read/write position.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:35
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
Success: Command worked.
Definition: mutt_commands.h:38
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
set current read/write position to offset from beginning
Definition: buffer.c:466
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:66
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:156
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_rc_line()

enum CommandResult mutt_parse_rc_line ( const char *  line,
struct Buffer err 
)

Parse a line of user config.

Parameters
lineConfig line to read
errWhere to write error messages
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 1038 of file init.c.

1039 {
1040  if (!line || (*line == '\0'))
1041  return MUTT_CMD_ERROR;
1042 
1043  struct Buffer *line_buffer = mutt_buffer_pool_get();
1044  struct Buffer *token = mutt_buffer_pool_get();
1045 
1046  mutt_buffer_strcpy(line_buffer, line);
1047 
1048  enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
1049 
1050  mutt_buffer_pool_release(&line_buffer);
1051  mutt_buffer_pool_release(&token);
1052  return rc;
1053 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
Error: Can&#39;t help the user.
Definition: mutt_commands.h:36
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
enum CommandResult mutt_parse_rc_buffer(struct Buffer *line, struct Buffer *token, struct Buffer *err)
Parse a line of user config.
Definition: init.c:980
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_query_variables()

int mutt_query_variables ( struct ListHead *  queries,
bool  show_docs 
)

Implement the -Q command line flag.

Parameters
queriesList of query strings
show_docsIf true, show one-liner docs for the config item
Return values
0Success, all queries exist
1Error

Definition at line 1062 of file init.c.

1063 {
1064  struct Buffer value = mutt_buffer_make(256);
1065  struct Buffer tmp = mutt_buffer_make(256);
1066  int rc = 0;
1067 
1068  struct ListNode *np = NULL;
1069  STAILQ_FOREACH(np, queries, entries)
1070  {
1071  mutt_buffer_reset(&value);
1072 
1073  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
1074  if (!he)
1075  {
1076  mutt_warning(_("No such variable: %s"), np->data);
1077  rc = 1;
1078  continue;
1079  }
1080 
1081  if (he->type & DT_DEPRECATED)
1082  {
1083  mutt_warning(_("Config variable '%s' is deprecated"), np->data);
1084  rc = 1;
1085  continue;
1086  }
1087 
1088  int rv = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1089  if (CSR_RESULT(rv) != CSR_SUCCESS)
1090  {
1091  rc = 1;
1092  continue;
1093  }
1094 
1095  int type = DTYPE(he->type);
1096  if (type == DT_PATH)
1097  mutt_pretty_mailbox(value.data, value.dsize);
1098 
1099  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) && (type != DT_QUAD))
1100  {
1101  mutt_buffer_reset(&tmp);
1102  pretty_var(value.data, &tmp);
1103  mutt_buffer_strcpy(&value, tmp.data);
1104  }
1105 
1106  dump_config_neo(NeoMutt->sub->cs, he, &value, NULL,
1107  show_docs ? CS_DUMP_SHOW_DOCS : CS_DUMP_NO_FLAGS, stdout);
1108  }
1109 
1110  mutt_buffer_dealloc(&value);
1111  mutt_buffer_dealloc(&tmp);
1112 
1113  return rc; // TEST16: neomutt -Q charset
1114 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define mutt_warning(...)
Definition: logging.h:82
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:525
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
#define DT_LONG
a number (long)
Definition: types.h:33
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:168
#define DT_QUAD
quad-option (no/yes/ask-no/ask-yes)
Definition: types.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
#define CSR_RESULT(x)
Definition: set.h:52
size_t dsize
Length of data.
Definition: buffer.h:37
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:341
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define DT_PATH
a path to a file/directory
Definition: types.h:36
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:77
#define CS_DUMP_NO_FLAGS
No flags are set.
Definition: dump.h:35
char * data
Pointer to data.
Definition: buffer.h:35
#define CS_DUMP_SHOW_DOCS
Show one-liner documentation for the config item.
Definition: dump.h:45
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * data
String.
Definition: list.h:36
void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
Dump the config in the style of NeoMutt.
Definition: dump.c:106
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
The item stored in a Hash Table.
Definition: hash.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
A List node for strings.
Definition: list.h:34
#define DT_NUMBER
a number
Definition: types.h:35
#define DT_BOOL
boolean option
Definition: types.h:30
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_command_complete()

int mutt_command_complete ( char *  buf,
size_t  buflen,
int  pos,
int  numtabs 
)

Complete a command name.

Parameters
bufBuffer for the result
buflenLength of the buffer
posCursor position in the buffer
numtabsNumber of times the user has hit 'tab'
Return values
1Success, a match
0Error, no match

Definition at line 1125 of file init.c.

1126 {
1127  char *pt = buf;
1128  int spaces; /* keep track of the number of leading spaces on the line */
1129  struct MyVar *myv = NULL;
1130 
1131  SKIPWS(buf);
1132  spaces = buf - pt;
1133 
1134  pt = buf + pos - spaces;
1135  while ((pt > buf) && !isspace((unsigned char) *pt))
1136  pt--;
1137 
1138  if (pt == buf) /* complete cmd */
1139  {
1140  /* first TAB. Collect all the matches */
1141  if (numtabs == 1)
1142  {
1143  NumMatched = 0;
1144  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1145  memset(Matches, 0, MatchesListsize);
1146  memset(Completed, 0, sizeof(Completed));
1147 
1148  struct Command *c = NULL;
1149  for (size_t num = 0, size = mutt_commands_array(&c); num < size; num++)
1150  candidate(UserTyped, c[num].name, Completed, sizeof(Completed));
1153 
1154  /* All matches are stored. Longest non-ambiguous string is ""
1155  * i.e. don't change 'buf'. Fake successful return this time */
1156  if (UserTyped[0] == '\0')
1157  return 1;
1158  }
1159 
1160  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1161  return 0;
1162 
1163  /* NumMatched will _always_ be at least 1 since the initial
1164  * user-typed string is always stored */
1165  if ((numtabs == 1) && (NumMatched == 2))
1166  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1167  else if ((numtabs > 1) && (NumMatched > 2))
1168  {
1169  /* cycle through all the matches */
1170  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1171  }
1172 
1173  /* return the completed command */
1174  strncpy(buf, Completed, buflen - spaces);
1175  }
1176  else if (mutt_str_startswith(buf, "set") || mutt_str_startswith(buf, "unset") ||
1177  mutt_str_startswith(buf, "reset") || mutt_str_startswith(buf, "toggle"))
1178  { /* complete variables */
1179  static const char *const prefixes[] = { "no", "inv", "?", "&", 0 };
1180 
1181  pt++;
1182  /* loop through all the possible prefixes (no, inv, ...) */
1183  if (mutt_str_startswith(buf, "set"))
1184  {
1185  for (int num = 0; prefixes[num]; num++)
1186  {
1187  if (mutt_str_startswith(pt, prefixes[num]))
1188  {
1189  pt += mutt_str_len(prefixes[num]);
1190  break;
1191  }
1192  }
1193  }
1194 
1195  /* first TAB. Collect all the matches */
1196  if (numtabs == 1)
1197  {
1198  NumMatched = 0;
1199  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1200  memset(Matches, 0, MatchesListsize);
1201  memset(Completed, 0, sizeof(Completed));
1202 
1203  struct HashElem *he = NULL;
1204  struct HashElem **list = get_elem_list(NeoMutt->sub->cs);
1205  for (size_t i = 0; list[i]; i++)
1206  {
1207  he = list[i];
1208  const int type = DTYPE(he->type);
1209 
1210  if ((type == DT_SYNONYM) || (type & DT_DEPRECATED))
1211  continue;
1212 
1213  candidate(UserTyped, he->key.strkey, Completed, sizeof(Completed));
1214  }
1215  FREE(&list);
1216 
1217  TAILQ_FOREACH(myv, &MyVars, entries)
1218  {
1219  candidate(UserTyped, myv->name, Completed, sizeof(Completed));
1220  }
1223 
1224  /* All matches are stored. Longest non-ambiguous string is ""
1225  * i.e. don't change 'buf'. Fake successful return this time */
1226  if (UserTyped[0] == '\0')
1227  return 1;
1228  }
1229 
1230  if ((Completed[0] == 0) && UserTyped[0])
1231  return 0;
1232 
1233  /* NumMatched will _always_ be at least 1 since the initial
1234  * user-typed string is always stored */
1235  if ((numtabs == 1) && (NumMatched == 2))
1236  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1237  else if ((numtabs > 1) && (NumMatched > 2))
1238  {
1239  /* cycle through all the matches */
1240  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1241  }
1242 
1243  strncpy(pt, Completed, buf + buflen - pt - spaces);
1244  }
1245  else if (mutt_str_startswith(buf, "exec"))
1246  {
1247  const enum MenuType mtype = menu_get_current_type();
1248  const struct Binding *menu = km_get_table(mtype);
1249  if (!menu && (mtype != MENU_PAGER))
1250  menu = OpGeneric;
1251 
1252  pt++;
1253  /* first TAB. Collect all the matches */
1254  if (numtabs == 1)
1255  {
1256  NumMatched = 0;
1257  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1258  memset(Matches, 0, MatchesListsize);
1259  memset(Completed, 0, sizeof(Completed));
1260  for (int num = 0; menu[num].name; num++)
1261  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1262  /* try the generic menu */
1263  if ((Completed[0] == '\0') && (mtype != MENU_PAGER))
1264  {
1265  menu = OpGeneric;
1266  for (int num = 0; menu[num].name; num++)
1267  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1268  }
1271 
1272  /* All matches are stored. Longest non-ambiguous string is ""
1273  * i.e. don't change 'buf'. Fake successful return this time */
1274  if (UserTyped[0] == '\0')
1275  return 1;
1276  }
1277 
1278  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1279  return 0;
1280 
1281  /* NumMatched will _always_ be at least 1 since the initial
1282  * user-typed string is always stored */
1283  if ((numtabs == 1) && (NumMatched == 2))
1284  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1285  else if ((numtabs > 1) && (NumMatched > 2))
1286  {
1287  /* cycle through all the matches */
1288  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1289  }
1290 
1291  strncpy(pt, Completed, buf + buflen - pt - spaces);
1292  }
1293  else
1294  return 0;
1295 
1296  return 1;
1297 }
union HashKey key
Key representing the data.
Definition: hash.h:46
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
static int NumMatched
Definition: init.c:81
MenuType
Types of GUI selections.
Definition: keymap.h:72
A user-callable command.
Definition: mutt_commands.h:45
const char * name
Name of the command.
Definition: mutt_commands.h:47
size_t mutt_commands_array(struct Command **first)
Get Commands array.
char * name
Name of user variable.
Definition: myvar.h:33
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define DTYPE(x)
Mask for the Data Type.
Definition: types.h:44
struct HashElem ** get_elem_list(struct ConfigSet *cs)
Create a sorted list of all config items.
Definition: subset.c:64
Pager pager (email viewer)
Definition: keymap.h:81
struct ConfigSet * cs
Parent ConfigSet.
Definition: subset.h:51
const struct Binding OpGeneric[]
Key bindings for the generic menu.
Definition: functions.c:53
A user-set variable.
Definition: myvar.h:31
struct MyVarList MyVars
List of all the user&#39;s custom config variables.
Definition: myvar.c:34
const char * name
name of the function
Definition: keymap.h:122
#define SKIPWS(ch)
Definition: string2.h:46
static char Completed[256]
Definition: init.c:82
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
static int MatchesListsize
Definition: init.c:85
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:96
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:77
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
#define DT_SYNONYM
synonym for another variable
Definition: types.h:42
static char UserTyped[1024]
Definition: init.c:79
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
const char * strkey
String key.
Definition: hash.h:36
static const char ** Matches
Definition: init.c:83
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1316
int type
Type of data stored in Hash Table, e.g. DT_STRING.
Definition: hash.h:45
#define FREE(x)
Definition: memory.h:40
The item stored in a Hash Table.
Definition: hash.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Mapping between a user key and a function.
Definition: keymap.h:120
static void candidate(char *user, const char *src, char *dest, size_t dlen)
helper function for completion
Definition: init.c:119
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_label_complete()

int mutt_label_complete ( char *  buf,
size_t  buflen,
int  numtabs 
)

Complete a label name.

Parameters
bufBuffer for the result
buflenLength of the buffer
numtabsNumber of times the user has hit 'tab'
Return values
1Success, a match
0Error, no match

Definition at line 1307 of file init.c.

1308 {
1309  char *pt = buf;
1310  int spaces; /* keep track of the number of leading spaces on the line */
1311 
1312  if (!Context || !Context->mailbox->label_hash)
1313  return 0;
1314 
1315  SKIPWS(buf);
1316  spaces = buf - pt;
1317 
1318  /* first TAB. Collect all the matches */
1319  if (numtabs == 1)
1320  {
1321  struct HashElem *entry = NULL;
1322  struct HashWalkState state = { 0 };
1323 
1324  NumMatched = 0;
1325  mutt_str_copy(UserTyped, buf, sizeof(UserTyped));
1326  memset(Matches, 0, MatchesListsize);
1327  memset(Completed, 0, sizeof(Completed));
1328  while ((entry = mutt_hash_walk(Context->mailbox->label_hash, &state)))
1329  candidate(UserTyped, entry->key.strkey, Completed, sizeof(Completed));
1331  qsort(Matches, NumMatched, sizeof(char *), (sort_t) mutt_istr_cmp);
1333 
1334  /* All matches are stored. Longest non-ambiguous string is ""
1335  * i.e. don't change 'buf'. Fake successful return this time */
1336  if (UserTyped[0] == '\0')
1337  return 1;
1338  }
1339 
1340  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1341  return 0;
1342 
1343  /* NumMatched will _always_ be at least 1 since the initial
1344  * user-typed string is always stored */
1345  if ((numtabs == 1) && (NumMatched == 2))
1346  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1347  else if ((numtabs > 1) && (NumMatched > 2))
1348  {
1349  /* cycle through all the matches */
1350  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1351  }
1352 
1353  /* return the completed label */
1354  strncpy(buf, Completed, buflen - spaces);
1355 
1356  return 1;
1357 }
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
The "current" mailbox.
Definition: context.h:37
union HashKey key
Key representing the data.
Definition: hash.h:46
static int NumMatched
Definition: init.c:81
struct HashTable * label_hash
Hash Table for x-labels.
Definition: mailbox.h:129
Cursor to iterate through a Hash Table.
Definition: hash.h:119
struct Mailbox * mailbox
Definition: context.h:49
#define SKIPWS(ch)
Definition: string2.h:46
static char Completed[256]
Definition: init.c:82
int(* sort_t)(const void *a, const void *b)
Prototype for a function to compare two emails.
Definition: sort.h:44
static int MatchesListsize
Definition: init.c:85
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:96
static char UserTyped[1024]
Definition: init.c:79
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
const char * strkey
String key.
Definition: hash.h:36
static const char ** Matches
Definition: init.c:83
struct HashElem * mutt_hash_walk(const struct HashTable *table, struct HashWalkState *state)
Iterate through all the HashElem&#39;s in a Hash Table.
Definition: hash.c:479
The item stored in a Hash Table.
Definition: hash.h:43
static void candidate(char *user, const char *src, char *dest, size_t dlen)
helper function for completion
Definition: init.c:119
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_nm_query_complete()

bool mutt_nm_query_complete ( char *  buf,
size_t  buflen,
int  pos,
int  numtabs 
)

Complete to the nearest notmuch tag.

Parameters
bufBuffer for the result
buflenLength of the buffer
posCursor position in the buffer
numtabsNumber of times the user has hit 'tab'
Return values
trueSuccess, a match
falseError, no match

Complete the nearest "tag:"-prefixed string previous to pos.

Definition at line 1371 of file init.c.

1372 {
1373  char *pt = buf;
1374  int spaces;
1375 
1376  SKIPWS(buf);
1377  spaces = buf - pt;
1378 
1379  pt = (char *) mutt_strn_rfind((char *) buf, pos, "tag:");
1380  if (pt)
1381  {
1382  pt += 4;
1383  if (numtabs == 1)
1384  {
1385  /* First TAB. Collect all the matches */
1387 
1388  /* All matches are stored. Longest non-ambiguous string is ""
1389  * i.e. don't change 'buf'. Fake successful return this time. */
1390  if (UserTyped[0] == '\0')
1391  return true;
1392  }
1393 
1394  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1395  return false;
1396 
1397  /* NumMatched will _always_ be at least 1 since the initial
1398  * user-typed string is always stored */
1399  if ((numtabs == 1) && (NumMatched == 2))
1400  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1401  else if ((numtabs > 1) && (NumMatched > 2))
1402  {
1403  /* cycle through all the matches */
1404  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1405  }
1406 
1407  /* return the completed query */
1408  strncpy(pt, Completed, buf + buflen - pt - spaces);
1409  }
1410  else
1411  return false;
1412 
1413  return true;
1414 }
static int NumMatched
Definition: init.c:81
#define SKIPWS(ch)
Definition: string2.h:46
static char Completed[256]
Definition: init.c:82
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:148
static char UserTyped[1024]
Definition: init.c:79
static const char ** Matches
Definition: init.c:83
const char * mutt_strn_rfind(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:920
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_nm_tag_complete()

bool mutt_nm_tag_complete ( char *  buf,
size_t  buflen,
int  numtabs 
)

Complete to the nearest notmuch tag.

Parameters
bufBuffer for the result
buflenLength of the buffer
numtabsNumber of times the user has hit 'tab'
Return values
trueSuccess, a match
falseError, no match

Complete the nearest "+" or "-" -prefixed string previous to pos.

Definition at line 1428 of file init.c.

1429 {
1430  if (!buf)
1431  return false;
1432 
1433  char *pt = buf;
1434 
1435  /* Only examine the last token */
1436  char *last_space = strrchr(buf, ' ');
1437  if (last_space)
1438  pt = (last_space + 1);
1439 
1440  /* Skip the +/- */
1441  if ((pt[0] == '+') || (pt[0] == '-'))
1442  pt++;
1443 
1444  if (numtabs == 1)
1445  {
1446  /* First TAB. Collect all the matches */
1448 
1449  /* All matches are stored. Longest non-ambiguous string is ""
1450  * i.e. don't change 'buf'. Fake successful return this time. */
1451  if (UserTyped[0] == '\0')
1452  return true;
1453  }
1454 
1455  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1456  return false;
1457 
1458  /* NumMatched will _always_ be at least 1 since the initial
1459  * user-typed string is always stored */
1460  if ((numtabs == 1) && (NumMatched == 2))
1461  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1462  else if ((numtabs > 1) && (NumMatched > 2))
1463  {
1464  /* cycle through all the matches */
1465  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1466  }
1467 
1468  /* return the completed query */
1469  strncpy(pt, Completed, buf + buflen - pt);
1470 
1471  return true;
1472 }
static int NumMatched
Definition: init.c:81
static char Completed[256]
Definition: init.c:82
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:148
static char UserTyped[1024]
Definition: init.c:79
static const char ** Matches
Definition: init.c:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_var_value_complete()

int mutt_var_value_complete ( char *  buf,
size_t  buflen,
int  pos 
)

Complete a variable/value.

Parameters
bufBuffer for the result
buflenLength of the buffer
posCursor position in the buffer

Definition at line 1481 of file init.c.

1482 {
1483  char *pt = buf;
1484 
1485  if (buf[0] == '\0')
1486  return 0;
1487 
1488  SKIPWS(buf);
1489  const int spaces = buf - pt;
1490 
1491  pt = buf + pos - spaces;
1492  while ((pt > buf) && !isspace((unsigned char) *pt))
1493  pt--;
1494  pt++; /* move past the space */
1495  if (*pt == '=') /* abort if no var before the '=' */
1496  return 0;
1497 
1498  if (mutt_str_startswith(buf, "set"))
1499  {
1500  const char *myvarval = NULL;
1501  char var[256];
1502  mutt_str_copy(var, pt, sizeof(var));
1503  /* ignore the trailing '=' when comparing */
1504  int vlen = mutt_str_len(var);
1505  if (vlen == 0)
1506  return 0;
1507 
1508  var[vlen - 1] = '\0';
1509 
1510  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, var);
1511  if (!he)
1512  {
1513  myvarval = myvar_get(var);
1514  if (myvarval)
1515  {
1516  struct Buffer pretty = mutt_buffer_make(256);
1517  pretty_var(myvarval, &pretty);
1518  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1519  mutt_buffer_dealloc(&pretty);
1520  return 1;
1521  }
1522  return 0; /* no such variable. */
1523  }
1524  else
1525  {
1526  struct Buffer value = mutt_buffer_make(256);
1527  struct Buffer pretty = mutt_buffer_make(256);
1528  int rc = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1529  if (CSR_RESULT(rc) == CSR_SUCCESS)
1530  {
1531  pretty_var(value.data, &pretty);
1532  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1533  mutt_buffer_dealloc(&value);
1534  mutt_buffer_dealloc(&pretty);
1535  return 0;
1536  }
1537  mutt_buffer_dealloc(&value);
1538  mutt_buffer_dealloc(&pretty);
1539  return 1;
1540  }
1541  }
1542  return 0;
1543 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
size_t pretty_var(const char *str, struct Buffer *buf)
Escape and stringify a config item value.
Definition: dump.c:83
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
struct HashElem * cs_subset_lookup(const struct ConfigSubset *sub, const char *name)
Find an inherited config item.
Definition: subset.c:168
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define CSR_RESULT(x)
Definition: set.h:52
int cs_subset_he_string_get(const struct ConfigSubset *sub, struct HashElem *he, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:341
#define SKIPWS(ch)
Definition: string2.h:46
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
char * data
Pointer to data.
Definition: buffer.h:35
const char * myvar_get(const char *var)
Get the value of a "my_" variable.
Definition: myvar.c:73
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
The item stored in a Hash Table.
Definition: hash.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ UserTyped

char UserTyped[1024] = { 0 }
static

Definition at line 79 of file init.c.

◆ NumMatched

int NumMatched = 0
static

Definition at line 81 of file init.c.

◆ Completed

char Completed[256] = { 0 }
static

Definition at line 82 of file init.c.

◆ Matches

const char** Matches
static

Definition at line 83 of file init.c.

◆ MatchesListsize

int MatchesListsize = 512
static

Definition at line 85 of file init.c.

◆ nm_tags

char** nm_tags
static

Definition at line 89 of file init.c.