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

Config/command parsing. More...

#include "config.h"
#include <ctype.h>
#include <inttypes.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 "compress/lib.h"
#include "hcache/lib.h"
#include "history/lib.h"
#include "notmuch/lib.h"
#include "store/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 "mutt_menu.h"
#include "mutt_parse.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

bool config_init_main (struct ConfigSet *cs)
 
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

◆ config_init_main()

bool config_init_main ( struct ConfigSet cs)

◆ matches_ensure_morespace()

static void matches_ensure_morespace ( int  current)
static

Allocate more space for auto-completion.

Parameters
currentCurrent allocation

Definition at line 103 of file init.c.

104 {
105  if (current <= (MatchesListsize - 2))
106  return;
107 
108  int base_space = 512; // Enough space for all of the config items
109  int extra_space = MatchesListsize - base_space;
110  extra_space *= 2;
111  const int space = base_space + extra_space;
112  mutt_mem_realloc(&Matches, space * sizeof(char *));
113  memset(&Matches[current + 1], 0, space - current);
114  MatchesListsize = space;
115 }
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:90
static const char ** Matches
Definition: init.c:88
+ 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 126 of file init.c.

127 {
128  if (!dest || !user || !src)
129  return;
130 
131  if (strstr(src, user) != src)
132  return;
133 
135  Matches[NumMatched++] = src;
136  if (dest[0] == '\0')
137  mutt_str_copy(dest, src, dlen);
138  else
139  {
140  int l;
141  for (l = 0; src[l] && src[l] == dest[l]; l++)
142  ; // do nothing
143 
144  dest[l] = '\0';
145  }
146 }
static int NumMatched
Definition: init.c:86
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:103
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:88
+ 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 155 of file init.c.

156 {
157  int tag_count_1 = 0;
158  int tag_count_2 = 0;
159 
160  NumMatched = 0;
161  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
162  memset(Matches, 0, MatchesListsize);
163  memset(Completed, 0, sizeof(Completed));
164 
166 
167  /* Work out how many tags there are. */
168  if (nm_get_all_tags(Context->mailbox, NULL, &tag_count_1) || (tag_count_1 == 0))
169  goto done;
170 
171  /* Free the old list, if any. */
172  if (nm_tags)
173  {
174  for (int i = 0; nm_tags[i]; i++)
175  FREE(&nm_tags[i]);
176  FREE(&nm_tags);
177  }
178  /* Allocate a new list, with sentinel. */
179  nm_tags = mutt_mem_malloc((tag_count_1 + 1) * sizeof(char *));
180  nm_tags[tag_count_1] = NULL;
181 
182  /* Get all the tags. */
183  if (nm_get_all_tags(Context->mailbox, nm_tags, &tag_count_2) || (tag_count_1 != tag_count_2))
184  {
185  FREE(&nm_tags);
186  nm_tags = NULL;
188  return -1;
189  }
190 
191  /* Put them into the completion machinery. */
192  for (int num = 0; num < tag_count_1; num++)
193  {
194  candidate(UserTyped, nm_tags[num], Completed, sizeof(Completed));
195  }
196 
199 
200 done:
202  return 0;
203 }
The "current" mailbox.
Definition: context.h:38
static int NumMatched
Definition: init.c:86
static char ** nm_tags
Definition: init.c:94
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:289
struct Mailbox * mailbox
Definition: context.h:50
static char Completed[256]
Definition: init.c:87
static int MatchesListsize
Definition: init.c:90
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:103
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:304
int nm_get_all_tags(struct Mailbox *m, char **tag_list, int *tag_count)
Fill a list with all notmuch tags.
Definition: notmuch.c:2141
static char UserTyped[1024]
Definition: init.c:84
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:88
#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:126
+ 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 212 of file init.c.

213 {
214  int rc = 0;
215  struct Buffer *err = mutt_buffer_pool_get();
216 
217  struct ListNode *np = NULL;
218  STAILQ_FOREACH(np, p, entries)
219  {
220  enum CommandResult rc2 = mutt_parse_rc_line(np->data, err);
221  if (rc2 == MUTT_CMD_ERROR)
222  mutt_error(_("Error in command line: %s"), mutt_buffer_string(err));
223  else if (rc2 == MUTT_CMD_WARNING)
224  mutt_warning(_("Warning in command line: %s"), mutt_buffer_string(err));
225 
226  if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
227  {
229  return -1;
230  }
231  }
233 
234  return rc;
235 }
#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:1046
#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 244 of file init.c.

245 {
246  const char *names[] = {
247  "neomuttrc",
248  "muttrc",
249  NULL,
250  };
251 
252  const char *locations[][2] = {
253  { xdg_cfg_home, "neomutt/" },
254  { xdg_cfg_home, "mutt/" },
255  { home, ".neomutt/" },
256  { home, ".mutt/" },
257  { home, "." },
258  { NULL, NULL },
259  };
260 
261  for (int i = 0; locations[i][0] || locations[i][1]; i++)
262  {
263  if (!locations[i][0])
264  continue;
265 
266  for (int j = 0; names[j]; j++)
267  {
268  char buf[256];
269 
270  snprintf(buf, sizeof(buf), "%s/%s%s", locations[i][0], locations[i][1], names[j]);
271  if (access(buf, F_OK) == 0)
272  return mutt_str_dup(buf);
273  }
274  }
275 
276  return NULL;
277 }
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
NULLif no valid mailname file could be read

Definition at line 285 of file init.c.

286 {
287  char *mailname = NULL;
288  static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
289 
290  for (size_t i = 0; i < mutt_array_size(mn_files); i++)
291  {
292  FILE *fp = mutt_file_fopen(mn_files[i], "r");
293  if (!fp)
294  continue;
295 
296  size_t len = 0;
297  mailname = mutt_file_read_line(NULL, &len, fp, NULL, MUTT_RL_NO_FLAGS);
298  mutt_file_fclose(&fp);
299  if (mailname && *mailname)
300  break;
301 
302  FREE(&mailname);
303  }
304 
305  return mailname;
306 }
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:39
#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 317 of file init.c.

318 {
319  char *str = NULL;
320  struct utsname utsname;
321 
322  if (C_Hostname)
323  {
324  str = C_Hostname;
325  }
326  else
327  {
328  /* The call to uname() shouldn't fail, but if it does, the system is horribly
329  * broken, and the system's networking configuration is in an unreliable
330  * state. We should bail. */
331  if ((uname(&utsname)) == -1)
332  {
333  mutt_perror(_("unable to determine nodename via uname()"));
334  return false; // TEST09: can't test
335  }
336 
337  str = utsname.nodename;
338  }
339 
340  /* some systems report the FQDN instead of just the hostname */
341  char *dot = strchr(str, '.');
342  if (dot)
343  ShortHostname = mutt_strn_dup(str, dot - str);
344  else
346 
347  if (!C_Hostname)
348  {
349  /* now get FQDN. Use configured domain first, DNS next, then uname */
350 #ifdef DOMAIN
351  /* we have a compile-time domain name, use that for `$hostname` */
353  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname), DOMAIN);
354 #else
355  C_Hostname = getmailname();
356  if (!C_Hostname)
357  {
358  struct Buffer *domain = mutt_buffer_pool_get();
359  if (getdnsdomainname(domain) == 0)
360  {
361  C_Hostname =
363  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname),
364  mutt_buffer_string(domain));
365  }
366  else
367  {
368  /* DNS failed, use the nodename. Whether or not the nodename had a '.'
369  * in it, we can use the nodename as the FQDN. On hosts where DNS is
370  * not being used, e.g. small network that relies on hosts files, a
371  * short host name is all that is required for SMTP to work correctly.
372  * It could be wrong, but we've done the best we can, at this point the
373  * onus is on the user to provide the correct hostname if the nodename
374  * won't work in their network. */
375  C_Hostname = mutt_str_dup(utsname.nodename);
376  }
377  mutt_buffer_pool_release(&domain);
378  }
379 #endif
380  }
381  if (C_Hostname)
382  cs_str_initial_set(cs, "hostname", C_Hostname, NULL);
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:285
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
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: mutt_globals.h:91
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:473
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:50
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
int getdnsdomainname(struct Buffer *domain)
Lookup the host&#39;s name using DNS.
Definition: getdomain.c:44
+ 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:76
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:79
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:74
#define MUTT_TOKEN_CONDENSE
^(char) to control chars (macros)
Definition: mutt.h:72
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:73
char * data
Pointer to data.
Definition: buffer.h:35
#define MUTT_TOKEN_PLUS
Treat &#39;+&#39; as a special.
Definition: mutt.h:81
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:77
#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:82
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:39
#define MUTT_TOKEN_BACKTICK_VARS
Expand variables within backticks.
Definition: mutt.h:78
#define FREE(x)
Definition: memory.h:40
#define MUTT_TOKEN_EQUAL
Treat &#39;=&#39; as a special.
Definition: mutt.h:71
#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:75
#define MUTT_TOKEN_QUESTION
Treat &#39;?&#39; as a special.
Definition: mutt.h:80
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 
647  mutt_regexlist_free(&Alternates);
651  mutt_regexlist_free(&UnAlternates);
654 
658 
659  /* Lists of strings */
660  mutt_list_free(&AlternativeOrderList);
661  mutt_list_free(&AutoViewList);
662  mutt_list_free(&HeaderOrderList);
665  mutt_list_free(&MimeLookupList);
666  mutt_list_free(&Muttrc);
668  mutt_list_free(&UserHeader);
669 
670  /* Lists of AttachMatch */
675 
677 
679  FREE(&HomeDir);
680  FREE(&LastFolder);
682  FREE(&Username);
683 
686 
688 
689  mutt_hist_free();
690  mutt_keys_free();
691 
694 }
struct RegexList SubscribedLists
List of regexes to match subscribed mailing lists.
Definition: globals.c:52
struct ReplaceList SubjectRegexList
List of regexes to tidy the view of the email&#39;s subject.
Definition: globals.c:53
struct ListHead InlineAllow
List of inline types to counted.
Definition: mutt_parse.c:41
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
void mutt_list_free_type(struct ListHead *h, list_free_t fn)
Free a List of type.
Definition: list.c:144
struct RegexList UnSubscribedLists
List of regexes to blacklist false matches in SubscribedLists.
Definition: globals.c:49
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:307
struct RegexList MailLists
List of regexes to match mailing lists.
Definition: globals.c:50
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:49
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:52
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:661
struct ListHead Ignore
List of header patterns to ignore.
Definition: globals.c:45
struct ListHead InlineExclude
List of inline types to ignore.
Definition: mutt_parse.c:42
struct RegexList NoSpamList
List of regexes to whitelist non-spam emails.
Definition: globals.c:43
void mutt_keys_free(void)
Free the key maps.
Definition: keymap.c:1698
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:47
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:38
Definition: color.h:129
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:55
void mutt_colors_free(struct Colors **ptr)
Free all the colours.
Definition: color.c:356
struct ReplaceList SpamList
List of regexes and patterns to match spam emails.
Definition: globals.c:44
struct ListHead AttachExclude
List of attachment types to be ignored.
Definition: mutt_parse.c:40
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: globals.c:46
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:54
struct RegexList UnMailLists
List of regexes to blacklist false matches in MailLists.
Definition: globals.c:51
#define FREE(x)
Definition: memory.h:40
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:44
void mutt_attachmatch_free(struct AttachMatch **ptr)
Free an AttachMatch - Implements list_free_t.
Definition: mutt_parse.c:243
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:59
struct ListHead AttachAllow
List of attachment types to be counted.
Definition: mutt_parse.c:39
void mutt_hist_free(void)
Free all the history lists.
Definition: history.c:424
void mutt_regexlist_free(struct RegexList *rl)
Free a RegexList object.
Definition: regex.c:171
void(* list_free_t)(void **ptr)
Prototype for a function to free List data.
Definition: list.h:45
+ 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 702 of file init.c.

703 {
704  struct Command *c = NULL;
705  for (size_t i = 0, size = mutt_commands_array(&c); i < size; i++)
706  {
707  if (((c[i].parse == mutt_parse_hook) || (c[i].parse == mutt_parse_idxfmt_hook)) &&
708  mutt_istr_equal(c[i].name, name))
709  {
710  return c[i].data;
711  }
712  }
713  return MUTT_HOOK_NO_FLAGS;
714 }
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:85
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:351
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:44
+ 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 724 of file init.c.

725 {
726  int need_pause = 0;
727  int rc = 1;
728  struct Buffer err = mutt_buffer_make(256);
729  struct Buffer buf = mutt_buffer_make(256);
730 
732  alias_init();
734 #ifdef USE_COMP_MBOX
735  mutt_comp_init();
736 #endif
737 #ifdef USE_IMAP
738  imap_init();
739 #endif
740 #ifdef USE_LUA
741  mutt_lua_init();
742 #endif
745 
746  mutt_menu_init();
747 #ifdef USE_SIDEBAR
748  sb_init();
749 #endif
750 #ifdef USE_NOTMUCH
751  nm_init();
752 #endif
753 
754  snprintf(AttachmentMarker, sizeof(AttachmentMarker), "\033]9;%" PRIu64 "\a", // Escape
755  mutt_rand64());
756 
757  snprintf(ProtectedHeaderMarker, sizeof(ProtectedHeaderMarker), "\033]8;%lld\a", // Escape
758  (long long) mutt_date_epoch());
759 
760  /* "$spoolfile" precedence: config file, environment */
761  const char *p = mutt_str_getenv("MAIL");
762  if (!p)
763  p = mutt_str_getenv("MAILDIR");
764  if (!p)
765  {
766 #ifdef HOMESPOOL
767  mutt_buffer_concat_path(&buf, NONULL(HomeDir), MAILPATH);
768 #else
769  mutt_buffer_concat_path(&buf, MAILPATH, NONULL(Username));
770 #endif
771  p = mutt_buffer_string(&buf);
772  }
773  cs_str_initial_set(cs, "spoolfile", p, NULL);
774  cs_str_reset(cs, "spoolfile", NULL);
775 
776  p = mutt_str_getenv("REPLYTO");
777  if (p)
778  {
779  struct Buffer token;
780 
781  mutt_buffer_printf(&buf, "Reply-To: %s", p);
782  mutt_buffer_init(&token);
783  parse_my_hdr(&token, &buf, 0, &err); /* adds to UserHeader */
784  FREE(&token.data);
785  }
786 
787  p = mutt_str_getenv("EMAIL");
788  if (p)
789  {
790  cs_str_initial_set(cs, "from", p, NULL);
791  cs_str_reset(cs, "from", NULL);
792  }
793 
794  /* "$mailcap_path" precedence: config file, environment, code */
795  const char *env_mc = mutt_str_getenv("MAILCAPS");
796  if (env_mc)
797  cs_str_string_set(cs, "mailcap_path", env_mc, NULL);
798 
799  /* "$tmpdir" precedence: config file, environment, code */
800  const char *env_tmp = mutt_str_getenv("TMPDIR");
801  if (env_tmp)
802  cs_str_string_set(cs, "tmpdir", env_tmp, NULL);
803 
804  /* "$visual", "$editor" precedence: config file, environment, code */
805  const char *env_ed = mutt_str_getenv("VISUAL");
806  if (!env_ed)
807  env_ed = mutt_str_getenv("EDITOR");
808  if (env_ed)
809  {
810  cs_str_string_set(cs, "editor", env_ed, NULL);
811  cs_str_string_set(cs, "visual", env_ed, NULL);
812  }
813 
815  cs_str_initial_set(cs, "charset", C_Charset, NULL);
817 
818  Matches = mutt_mem_calloc(MatchesListsize, sizeof(char *));
819 
821 
822 #ifdef HAVE_GETSID
823  /* Unset suspend by default if we're the session leader */
824  if (getsid(0) == getpid())
825  C_Suspend = false;
826 #endif
827 
828  /* RFC2368, "4. Unsafe headers"
829  * The creator of a mailto URL can't expect the resolver of a URL to
830  * understand more than the "subject" and "body" headers. Clients that
831  * resolve mailto URLs into mail messages should be able to correctly
832  * create RFC822-compliant mail messages using the "subject" and "body"
833  * headers. */
834  add_to_stailq(&MailToAllow, "body");
835  add_to_stailq(&MailToAllow, "subject");
836  /* Cc, In-Reply-To, and References help with not breaking threading on
837  * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
838  add_to_stailq(&MailToAllow, "cc");
839  add_to_stailq(&MailToAllow, "in-reply-to");
840  add_to_stailq(&MailToAllow, "references");
841 
842  if (STAILQ_EMPTY(&Muttrc))
843  {
844  const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
845 
846  if (!xdg_cfg_home && HomeDir)
847  {
848  mutt_buffer_printf(&buf, "%s/.config", HomeDir);
849  xdg_cfg_home = mutt_buffer_string(&buf);
850  }
851 
852  char *config = find_cfg(HomeDir, xdg_cfg_home);
853  if (config)
854  {
855  mutt_list_insert_tail(&Muttrc, config);
856  }
857  }
858  else
859  {
860  struct ListNode *np = NULL;
861  STAILQ_FOREACH(np, &Muttrc, entries)
862  {
863  mutt_buffer_strcpy(&buf, np->data);
864  FREE(&np->data);
866  np->data = mutt_buffer_strdup(&buf);
867  if (access(np->data, F_OK))
868  {
869  mutt_perror(np->data);
870  goto done; // TEST10: neomutt -F missing
871  }
872  }
873  }
874 
875  if (!STAILQ_EMPTY(&Muttrc))
876  {
877  cs_str_string_set(cs, "alias_file", STAILQ_FIRST(&Muttrc)->data, NULL);
878  }
879 
880  /* Process the global rc file if it exists and the user hasn't explicitly
881  * requested not to via "-n". */
882  if (!skip_sys_rc)
883  {
884  do
885  {
887  break;
888 
889  mutt_buffer_printf(&buf, "%s/neomuttrc", SYSCONFDIR);
890  if (access(mutt_buffer_string(&buf), F_OK) == 0)
891  break;
892 
893  mutt_buffer_printf(&buf, "%s/Muttrc", SYSCONFDIR);
894  if (access(mutt_buffer_string(&buf), F_OK) == 0)
895  break;
896 
897  mutt_buffer_printf(&buf, "%s/neomuttrc", PKGDATADIR);
898  if (access(mutt_buffer_string(&buf), F_OK) == 0)
899  break;
900 
901  mutt_buffer_printf(&buf, "%s/Muttrc", PKGDATADIR);
902  } while (false);
903 
904  if (access(mutt_buffer_string(&buf), F_OK) == 0)
905  {
906  if (source_rc(mutt_buffer_string(&buf), &err) != 0)
907  {
908  mutt_error("%s", err.data);
909  need_pause = 1; // TEST11: neomutt (error in /etc/neomuttrc)
910  }
911  }
912  }
913 
914  /* Read the user's initialization file. */
915  struct ListNode *np = NULL;
916  STAILQ_FOREACH(np, &Muttrc, entries)
917  {
918  if (np->data)
919  {
920  if (source_rc(np->data, &err) != 0)
921  {
922  mutt_error("%s", err.data);
923  need_pause = 1; // TEST12: neomutt (error in ~/.neomuttrc)
924  }
925  }
926  }
927 
928  if (execute_commands(commands) != 0)
929  need_pause = 1; // TEST13: neomutt -e broken
930 
931  if (!get_hostname(cs))
932  goto done;
933 
934  if (!C_Realname)
935  {
936  struct passwd *pw = getpwuid(getuid());
937  if (pw)
938  {
939  char name[256];
940  C_Realname = mutt_str_dup(mutt_gecos_name(name, sizeof(name), pw));
941  }
942  }
943  cs_str_initial_set(cs, "realname", C_Realname, NULL);
944 
945  if (need_pause && !OptNoCurses)
946  {
948  if (mutt_any_key_to_continue(NULL) == 'q')
949  goto done; // TEST14: neomutt -e broken (press 'q')
950  }
951 
952  mutt_file_mkdir(C_Tmpdir, S_IRWXU);
953 
954  mutt_hist_init();
956 
957 #ifdef USE_NOTMUCH
958  if (C_VirtualSpoolfile)
959  {
960  /* Find the first virtual folder and open it */
961  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
963  struct MailboxNode *mp = STAILQ_FIRST(&ml);
964  if (mp)
965  cs_str_string_set(cs, "spoolfile", mailbox_path(mp->mailbox), NULL);
967  }
968 #endif
969  rc = 0;
970 
971 done:
972  mutt_buffer_dealloc(&err);
973  mutt_buffer_dealloc(&buf);
974  return rc;
975 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
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:204
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:66
#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
void mutt_ch_set_charset(const char *charset)
Update the records for a new character set.
Definition: charset.c:1003
#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:212
WHERE char * C_Realname
Config: Real name of the user.
Definition: mutt_globals.h:105
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:653
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:613
Index panel (list of emails)
Definition: keymap.h:80
void imap_init(void)
Setup feature commands.
Definition: imap.c:79
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:244
Container for Accounts, Notifications.
Definition: neomutt.h:36
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:49
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 ProtectedHeaderMarker[256]
Unique ANSI string to mark protected headers in an email.
Definition: mutt_globals.h:47
WHERE char * Username
User&#39;s login name.
Definition: mutt_globals.h:52
#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:568
WHERE enum MenuType CurrentMenu
Current Menu, e.g. MENU_PAGER.
Definition: mutt_globals.h:77
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:875
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:473
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:1703
WHERE bool C_Suspend
Config: Allow the user to suspend NeoMutt using &#39;^Z&#39;.
Definition: mutt_globals.h:165
void nm_init(void)
Setup feature commands.
Definition: notmuch.c:88
static int MatchesListsize
Definition: init.c:90
void mutt_grouplist_init(void)
Initialize the GroupList singleton.
Definition: group.c:45
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: random.c:129
WHERE char AttachmentMarker[256]
Unique ANSI string to mark PGP messages in an email.
Definition: mutt_globals.h:46
struct ListHead MailToAllow
List of permitted fields in a mailto: url.
Definition: globals.c:47
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:317
struct HashTable * TagTransforms
Lookup table of alternative tag names.
Definition: tags.c:38
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
void mutt_hist_init(void)
Create a set of empty History ring buffers.
Definition: history.c:447
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:1500
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
char * data
String.
Definition: list.h:36
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
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:362
#define mutt_error(...)
Definition: logging.h:84
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:56
static const char ** Matches
Definition: init.c:88
#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:408
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:59
A List node for strings.
Definition: list.h:34
XDG system dir: /etc/xdg.
Definition: protos.h:48
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
char * mutt_ch_get_langinfo_charset(void)
Get the user&#39;s choice of character set.
Definition: charset.c:462
#define STAILQ_FIRST(head)
Definition: queue.h:347
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:97
bool C_VirtualSpoolfile
Config: (notmuch) Use the first virtual mailbox as a spool file.
Definition: config.c:51
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 988 of file init.c.

990 {
991  if (mutt_buffer_len(line) == 0)
992  return 0;
993 
995 
996  mutt_buffer_reset(err);
997 
998  /* Read from the beginning of line->data */
999  mutt_buffer_seek(line, 0);
1000 
1001  SKIPWS(line->dptr);
1002  while (*line->dptr)
1003  {
1004  if (*line->dptr == '#')
1005  break; /* rest of line is a comment */
1006  if (*line->dptr == ';')
1007  {
1008  line->dptr++;
1009  continue;
1010  }
1012 
1013  struct Command *cmd = NULL;
1014  size_t size = mutt_commands_array(&cmd);
1015  size_t i;
1016  for (i = 0; i < size; i++)
1017  {
1018  if (mutt_str_equal(token->data, cmd[i].name))
1019  {
1020  rc = cmd[i].parse(token, line, cmd[i].data, err);
1021  if (rc != MUTT_CMD_SUCCESS)
1022  { /* -1 Error, +1 Finish */
1023  goto finish; /* Propagate return code */
1024  }
1025  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) cmd);
1026  break; /* Continue with next command */
1027  }
1028  }
1029  if (i == size)
1030  {
1031  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1032  rc = MUTT_CMD_ERROR;
1033  break; /* Ignore the rest of the line */
1034  }
1035  }
1036 finish:
1037  return rc;
1038 }
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:36
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:70
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:152
+ 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 1046 of file init.c.

1047 {
1048  if (!line || (*line == '\0'))
1049  return MUTT_CMD_ERROR;
1050 
1051  struct Buffer *line_buffer = mutt_buffer_pool_get();
1052  struct Buffer *token = mutt_buffer_pool_get();
1053 
1054  mutt_buffer_strcpy(line_buffer, line);
1055 
1056  enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
1057 
1058  mutt_buffer_pool_release(&line_buffer);
1059  mutt_buffer_pool_release(&token);
1060  return rc;
1061 }
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:988
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 1070 of file init.c.

1071 {
1072  struct Buffer value = mutt_buffer_make(256);
1073  struct Buffer tmp = mutt_buffer_make(256);
1074  int rc = 0;
1075 
1076  struct ListNode *np = NULL;
1077  STAILQ_FOREACH(np, queries, entries)
1078  {
1079  mutt_buffer_reset(&value);
1080 
1081  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, np->data);
1082  if (!he)
1083  {
1084  mutt_warning(_("No such variable: %s"), np->data);
1085  rc = 1;
1086  continue;
1087  }
1088 
1089  if (he->type & DT_DEPRECATED)
1090  {
1091  mutt_warning(_("Config variable '%s' is deprecated"), np->data);
1092  rc = 1;
1093  continue;
1094  }
1095 
1096  int rv = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1097  if (CSR_RESULT(rv) != CSR_SUCCESS)
1098  {
1099  rc = 1;
1100  continue;
1101  }
1102 
1103  int type = DTYPE(he->type);
1104  if (type == DT_PATH)
1105  mutt_pretty_mailbox(value.data, value.dsize);
1106 
1107  if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) && (type != DT_QUAD))
1108  {
1109  mutt_buffer_reset(&tmp);
1110  pretty_var(value.data, &tmp);
1111  mutt_buffer_strcpy(&value, tmp.data);
1112  }
1113 
1114  dump_config_neo(NeoMutt->sub->cs, he, &value, NULL,
1115  show_docs ? CS_DUMP_SHOW_DOCS : CS_DUMP_NO_FLAGS, stdout);
1116  }
1117 
1118  mutt_buffer_dealloc(&value);
1119  mutt_buffer_dealloc(&tmp);
1120 
1121  return rc; // TEST16: neomutt -Q charset
1122 }
#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:523
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:79
#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 1133 of file init.c.

1134 {
1135  char *pt = buf;
1136  int spaces; /* keep track of the number of leading spaces on the line */
1137  struct MyVar *myv = NULL;
1138 
1139  SKIPWS(buf);
1140  spaces = buf - pt;
1141 
1142  pt = buf + pos - spaces;
1143  while ((pt > buf) && !isspace((unsigned char) *pt))
1144  pt--;
1145 
1146  if (pt == buf) /* complete cmd */
1147  {
1148  /* first TAB. Collect all the matches */
1149  if (numtabs == 1)
1150  {
1151  NumMatched = 0;
1152  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1153  memset(Matches, 0, MatchesListsize);
1154  memset(Completed, 0, sizeof(Completed));
1155 
1156  struct Command *c = NULL;
1157  for (size_t num = 0, size = mutt_commands_array(&c); num < size; num++)
1158  candidate(UserTyped, c[num].name, Completed, sizeof(Completed));
1161 
1162  /* All matches are stored. Longest non-ambiguous string is ""
1163  * i.e. don't change 'buf'. Fake successful return this time */
1164  if (UserTyped[0] == '\0')
1165  return 1;
1166  }
1167 
1168  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1169  return 0;
1170 
1171  /* NumMatched will _always_ be at least 1 since the initial
1172  * user-typed string is always stored */
1173  if ((numtabs == 1) && (NumMatched == 2))
1174  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1175  else if ((numtabs > 1) && (NumMatched > 2))
1176  {
1177  /* cycle through all the matches */
1178  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1179  }
1180 
1181  /* return the completed command */
1182  strncpy(buf, Completed, buflen - spaces);
1183  }
1184  else if (mutt_str_startswith(buf, "set") || mutt_str_startswith(buf, "unset") ||
1185  mutt_str_startswith(buf, "reset") || mutt_str_startswith(buf, "toggle"))
1186  { /* complete variables */
1187  static const char *const prefixes[] = { "no", "inv", "?", "&", 0 };
1188 
1189  pt++;
1190  /* loop through all the possible prefixes (no, inv, ...) */
1191  if (mutt_str_startswith(buf, "set"))
1192  {
1193  for (int num = 0; prefixes[num]; num++)
1194  {
1195  if (mutt_str_startswith(pt, prefixes[num]))
1196  {
1197  pt += mutt_str_len(prefixes[num]);
1198  break;
1199  }
1200  }
1201  }
1202 
1203  /* first TAB. Collect all the matches */
1204  if (numtabs == 1)
1205  {
1206  NumMatched = 0;
1207  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1208  memset(Matches, 0, MatchesListsize);
1209  memset(Completed, 0, sizeof(Completed));
1210 
1211  struct HashElem *he = NULL;
1212  struct HashElem **list = get_elem_list(NeoMutt->sub->cs);
1213  for (size_t i = 0; list[i]; i++)
1214  {
1215  he = list[i];
1216  const int type = DTYPE(he->type);
1217 
1218  if ((type == DT_SYNONYM) || (type & DT_DEPRECATED))
1219  continue;
1220 
1221  candidate(UserTyped, he->key.strkey, Completed, sizeof(Completed));
1222  }
1223  FREE(&list);
1224 
1225  TAILQ_FOREACH(myv, &MyVars, entries)
1226  {
1227  candidate(UserTyped, myv->name, Completed, sizeof(Completed));
1228  }
1231 
1232  /* All matches are stored. Longest non-ambiguous string is ""
1233  * i.e. don't change 'buf'. Fake successful return this time */
1234  if (UserTyped[0] == '\0')
1235  return 1;
1236  }
1237 
1238  if ((Completed[0] == 0) && UserTyped[0])
1239  return 0;
1240 
1241  /* NumMatched will _always_ be at least 1 since the initial
1242  * user-typed string is always stored */
1243  if ((numtabs == 1) && (NumMatched == 2))
1244  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1245  else if ((numtabs > 1) && (NumMatched > 2))
1246  {
1247  /* cycle through all the matches */
1248  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1249  }
1250 
1251  strncpy(pt, Completed, buf + buflen - pt - spaces);
1252  }
1253  else if (mutt_str_startswith(buf, "exec"))
1254  {
1255  const struct Binding *menu = km_get_table(CurrentMenu);
1256 
1257  if (!menu && (CurrentMenu != MENU_PAGER))
1258  menu = OpGeneric;
1259 
1260  pt++;
1261  /* first TAB. Collect all the matches */
1262  if (numtabs == 1)
1263  {
1264  NumMatched = 0;
1265  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
1266  memset(Matches, 0, MatchesListsize);
1267  memset(Completed, 0, sizeof(Completed));
1268  for (int num = 0; menu[num].name; num++)
1269  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1270  /* try the generic menu */
1271  if ((Completed[0] == '\0') && (CurrentMenu != MENU_PAGER))
1272  {
1273  menu = OpGeneric;
1274  for (int num = 0; menu[num].name; num++)
1275  candidate(UserTyped, menu[num].name, Completed, sizeof(Completed));
1276  }
1279 
1280  /* All matches are stored. Longest non-ambiguous string is ""
1281  * i.e. don't change 'buf'. Fake successful return this time */
1282  if (UserTyped[0] == '\0')
1283  return 1;
1284  }
1285 
1286  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1287  return 0;
1288 
1289  /* NumMatched will _always_ be at least 1 since the initial
1290  * user-typed string is always stored */
1291  if ((numtabs == 1) && (NumMatched == 2))
1292  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1293  else if ((numtabs > 1) && (NumMatched > 2))
1294  {
1295  /* cycle through all the matches */
1296  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1297  }
1298 
1299  strncpy(pt, Completed, buf + buflen - pt - spaces);
1300  }
1301  else
1302  return 0;
1303 
1304  return 1;
1305 }
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:86
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
WHERE enum MenuType CurrentMenu
Current Menu, e.g. MENU_PAGER.
Definition: mutt_globals.h:77
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:87
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:90
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:103
#define DT_DEPRECATED
Config item shouldn&#39;t be used any more.
Definition: types.h:79
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:84
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:88
const struct Binding * km_get_table(enum MenuType menu)
Lookup a menu&#39;s keybindings.
Definition: keymap.c:1306
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:126
+ 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 1315 of file init.c.

1316 {
1317  char *pt = buf;
1318  int spaces; /* keep track of the number of leading spaces on the line */
1319 
1320  if (!Context || !Context->mailbox->label_hash)
1321  return 0;
1322 
1323  SKIPWS(buf);
1324  spaces = buf - pt;
1325 
1326  /* first TAB. Collect all the matches */
1327  if (numtabs == 1)
1328  {
1329  struct HashElem *entry = NULL;
1330  struct HashWalkState state = { 0 };
1331 
1332  NumMatched = 0;
1333  mutt_str_copy(UserTyped, buf, sizeof(UserTyped));
1334  memset(Matches, 0, MatchesListsize);
1335  memset(Completed, 0, sizeof(Completed));
1336  while ((entry = mutt_hash_walk(Context->mailbox->label_hash, &state)))
1337  candidate(UserTyped, entry->key.strkey, Completed, sizeof(Completed));
1339  qsort(Matches, NumMatched, sizeof(char *), (sort_t) mutt_istr_cmp);
1341 
1342  /* All matches are stored. Longest non-ambiguous string is ""
1343  * i.e. don't change 'buf'. Fake successful return this time */
1344  if (UserTyped[0] == '\0')
1345  return 1;
1346  }
1347 
1348  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1349  return 0;
1350 
1351  /* NumMatched will _always_ be at least 1 since the initial
1352  * user-typed string is always stored */
1353  if ((numtabs == 1) && (NumMatched == 2))
1354  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1355  else if ((numtabs > 1) && (NumMatched > 2))
1356  {
1357  /* cycle through all the matches */
1358  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1359  }
1360 
1361  /* return the completed label */
1362  strncpy(buf, Completed, buflen - spaces);
1363 
1364  return 1;
1365 }
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:38
union HashKey key
Key representing the data.
Definition: hash.h:46
static int NumMatched
Definition: init.c:86
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:50
#define SKIPWS(ch)
Definition: string2.h:46
static char Completed[256]
Definition: init.c:87
int(* sort_t)(const void *a, const void *b)
Prototype for a function to compare two emails.
Definition: sort.h:50
static int MatchesListsize
Definition: init.c:90
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:103
static char UserTyped[1024]
Definition: init.c:84
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:88
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:126
+ 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 1379 of file init.c.

1380 {
1381  char *pt = buf;
1382  int spaces;
1383 
1384  SKIPWS(buf);
1385  spaces = buf - pt;
1386 
1387  pt = (char *) mutt_strn_rfind((char *) buf, pos, "tag:");
1388  if (pt)
1389  {
1390  pt += 4;
1391  if (numtabs == 1)
1392  {
1393  /* First TAB. Collect all the matches */
1395 
1396  /* All matches are stored. Longest non-ambiguous string is ""
1397  * i.e. don't change 'buf'. Fake successful return this time. */
1398  if (UserTyped[0] == '\0')
1399  return true;
1400  }
1401 
1402  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1403  return false;
1404 
1405  /* NumMatched will _always_ be at least 1 since the initial
1406  * user-typed string is always stored */
1407  if ((numtabs == 1) && (NumMatched == 2))
1408  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1409  else if ((numtabs > 1) && (NumMatched > 2))
1410  {
1411  /* cycle through all the matches */
1412  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1413  }
1414 
1415  /* return the completed query */
1416  strncpy(pt, Completed, buf + buflen - pt - spaces);
1417  }
1418  else
1419  return false;
1420 
1421  return true;
1422 }
static int NumMatched
Definition: init.c:86
#define SKIPWS(ch)
Definition: string2.h:46
static char Completed[256]
Definition: init.c:87
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:155
static char UserTyped[1024]
Definition: init.c:84
static const char ** Matches
Definition: init.c:88
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 1436 of file init.c.

1437 {
1438  if (!buf)
1439  return false;
1440 
1441  char *pt = buf;
1442 
1443  /* Only examine the last token */
1444  char *last_space = strrchr(buf, ' ');
1445  if (last_space)
1446  pt = (last_space + 1);
1447 
1448  /* Skip the +/- */
1449  if ((pt[0] == '+') || (pt[0] == '-'))
1450  pt++;
1451 
1452  if (numtabs == 1)
1453  {
1454  /* First TAB. Collect all the matches */
1456 
1457  /* All matches are stored. Longest non-ambiguous string is ""
1458  * i.e. don't change 'buf'. Fake successful return this time. */
1459  if (UserTyped[0] == '\0')
1460  return true;
1461  }
1462 
1463  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1464  return false;
1465 
1466  /* NumMatched will _always_ be at least 1 since the initial
1467  * user-typed string is always stored */
1468  if ((numtabs == 1) && (NumMatched == 2))
1469  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1470  else if ((numtabs > 1) && (NumMatched > 2))
1471  {
1472  /* cycle through all the matches */
1473  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1474  }
1475 
1476  /* return the completed query */
1477  strncpy(pt, Completed, buf + buflen - pt);
1478 
1479  return true;
1480 }
static int NumMatched
Definition: init.c:86
static char Completed[256]
Definition: init.c:87
static int complete_all_nm_tags(const char *pt)
Pass a list of Notmuch tags to the completion code.
Definition: init.c:155
static char UserTyped[1024]
Definition: init.c:84
static const char ** Matches
Definition: init.c:88
+ 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 1489 of file init.c.

1490 {
1491  char *pt = buf;
1492 
1493  if (buf[0] == '\0')
1494  return 0;
1495 
1496  SKIPWS(buf);
1497  const int spaces = buf - pt;
1498 
1499  pt = buf + pos - spaces;
1500  while ((pt > buf) && !isspace((unsigned char) *pt))
1501  pt--;
1502  pt++; /* move past the space */
1503  if (*pt == '=') /* abort if no var before the '=' */
1504  return 0;
1505 
1506  if (mutt_str_startswith(buf, "set"))
1507  {
1508  const char *myvarval = NULL;
1509  char var[256];
1510  mutt_str_copy(var, pt, sizeof(var));
1511  /* ignore the trailing '=' when comparing */
1512  int vlen = mutt_str_len(var);
1513  if (vlen == 0)
1514  return 0;
1515 
1516  var[vlen - 1] = '\0';
1517 
1518  struct HashElem *he = cs_subset_lookup(NeoMutt->sub, var);
1519  if (!he)
1520  {
1521  myvarval = myvar_get(var);
1522  if (myvarval)
1523  {
1524  struct Buffer pretty = mutt_buffer_make(256);
1525  pretty_var(myvarval, &pretty);
1526  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1527  mutt_buffer_dealloc(&pretty);
1528  return 1;
1529  }
1530  return 0; /* no such variable. */
1531  }
1532  else
1533  {
1534  struct Buffer value = mutt_buffer_make(256);
1535  struct Buffer pretty = mutt_buffer_make(256);
1536  int rc = cs_subset_he_string_get(NeoMutt->sub, he, &value);
1537  if (CSR_RESULT(rc) == CSR_SUCCESS)
1538  {
1539  pretty_var(value.data, &pretty);
1540  snprintf(pt, buflen - (pt - buf), "%s=%s", var, pretty.data);
1541  mutt_buffer_dealloc(&value);
1542  mutt_buffer_dealloc(&pretty);
1543  return 0;
1544  }
1545  mutt_buffer_dealloc(&value);
1546  mutt_buffer_dealloc(&pretty);
1547  return 1;
1548  }
1549  }
1550  return 0;
1551 }
#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 84 of file init.c.

◆ NumMatched

int NumMatched = 0
static

Definition at line 86 of file init.c.

◆ Completed

char Completed[256] = { 0 }
static

Definition at line 87 of file init.c.

◆ Matches

const char** Matches
static

Definition at line 88 of file init.c.

◆ MatchesListsize

int MatchesListsize = 512
static

Definition at line 90 of file init.c.

◆ nm_tags

char** nm_tags
static

Definition at line 94 of file init.c.