NeoMutt  2020-11-20
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_b2s(err));
223  else if (rc2 == MUTT_CMD_WARNING)
224  mutt_warning(_("Warning in command line: %s"), mutt_b2s(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:1039
#define _(a)
Definition: message.h:28
#define mutt_b2s(buf)
Definition: buffer.h:41
#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, 0);
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, int 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 FREE(x)
Definition: memory.h:40
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ 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), mutt_b2s(domain));
364  }
365  else
366  {
367  /* DNS failed, use the nodename. Whether or not the nodename had a '.'
368  * in it, we can use the nodename as the FQDN. On hosts where DNS is
369  * not being used, e.g. small network that relies on hosts files, a
370  * short host name is all that is required for SMTP to work correctly.
371  * It could be wrong, but we've done the best we can, at this point the
372  * onus is on the user to provide the correct hostname if the nodename
373  * won't work in their network. */
374  C_Hostname = mutt_str_dup(utsname.nodename);
375  }
376  mutt_buffer_pool_release(&domain);
377  }
378 #endif
379  }
380  if (C_Hostname)
381  cs_str_initial_set(cs, "hostname", C_Hostname, NULL);
382 
383  return true;
384 }
#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
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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 394 of file init.c.

395 {
396  if (!dest || !tok)
397  return -1;
398 
399  char ch;
400  char qc = '\0'; /* quote char */
401  char *pc = NULL;
402 
403  mutt_buffer_reset(dest);
404 
405  SKIPWS(tok->dptr);
406  while ((ch = *tok->dptr))
407  {
408  if (qc == '\0')
409  {
410  if ((IS_SPACE(ch) && !(flags & MUTT_TOKEN_SPACE)) ||
411  ((ch == '#') && !(flags & MUTT_TOKEN_COMMENT)) ||
412  ((ch == '+') && (flags & MUTT_TOKEN_PLUS)) ||
413  ((ch == '-') && (flags & MUTT_TOKEN_MINUS)) ||
414  ((ch == '=') && (flags & MUTT_TOKEN_EQUAL)) ||
415  ((ch == '?') && (flags & MUTT_TOKEN_QUESTION)) ||
416  ((ch == ';') && !(flags & MUTT_TOKEN_SEMICOLON)) ||
417  ((flags & MUTT_TOKEN_PATTERN) && strchr("~%=!|", ch)))
418  {
419  break;
420  }
421  }
422 
423  tok->dptr++;
424 
425  if (ch == qc)
426  qc = 0; /* end of quote */
427  else if (!qc && ((ch == '\'') || (ch == '"')) && !(flags & MUTT_TOKEN_QUOTE))
428  qc = ch;
429  else if ((ch == '\\') && (qc != '\''))
430  {
431  if (tok->dptr[0] == '\0')
432  return -1; /* premature end of token */
433  switch (ch = *tok->dptr++)
434  {
435  case 'c':
436  case 'C':
437  if (tok->dptr[0] == '\0')
438  return -1; /* premature end of token */
439  mutt_buffer_addch(dest, (toupper((unsigned char) tok->dptr[0]) - '@') & 0x7f);
440  tok->dptr++;
441  break;
442  case 'e':
443  mutt_buffer_addch(dest, '\033'); // Escape
444  break;
445  case 'f':
446  mutt_buffer_addch(dest, '\f');
447  break;
448  case 'n':
449  mutt_buffer_addch(dest, '\n');
450  break;
451  case 'r':
452  mutt_buffer_addch(dest, '\r');
453  break;
454  case 't':
455  mutt_buffer_addch(dest, '\t');
456  break;
457  default:
458  if (isdigit((unsigned char) ch) && isdigit((unsigned char) tok->dptr[0]) &&
459  isdigit((unsigned char) tok->dptr[1]))
460  {
461  mutt_buffer_addch(dest, (ch << 6) + (tok->dptr[0] << 3) + tok->dptr[1] - 3504);
462  tok->dptr += 2;
463  }
464  else
465  mutt_buffer_addch(dest, ch);
466  }
467  }
468  else if ((ch == '^') && (flags & MUTT_TOKEN_CONDENSE))
469  {
470  if (tok->dptr[0] == '\0')
471  return -1; /* premature end of token */
472  ch = *tok->dptr++;
473  if (ch == '^')
474  mutt_buffer_addch(dest, ch);
475  else if (ch == '[')
476  mutt_buffer_addch(dest, '\033'); // Escape
477  else if (isalpha((unsigned char) ch))
478  mutt_buffer_addch(dest, toupper((unsigned char) ch) - '@');
479  else
480  {
481  mutt_buffer_addch(dest, '^');
482  mutt_buffer_addch(dest, ch);
483  }
484  }
485  else if ((ch == '`') && (!qc || (qc == '"')))
486  {
487  FILE *fp = NULL;
488  pid_t pid;
489 
490  pc = tok->dptr;
491  do
492  {
493  pc = strpbrk(pc, "\\`");
494  if (pc)
495  {
496  /* skip any quoted chars */
497  if (*pc == '\\')
498  pc += 2;
499  }
500  } while (pc && (pc[0] != '`'));
501  if (!pc)
502  {
503  mutt_debug(LL_DEBUG1, "mismatched backticks\n");
504  return -1;
505  }
506  struct Buffer cmd;
507  mutt_buffer_init(&cmd);
508  *pc = '\0';
509  if (flags & MUTT_TOKEN_BACKTICK_VARS)
510  {
511  /* recursively extract tokens to interpolate variables */
512  mutt_extract_token(&cmd, tok,
513  MUTT_TOKEN_QUOTE | MUTT_TOKEN_SPACE | MUTT_TOKEN_COMMENT |
514  MUTT_TOKEN_SEMICOLON | MUTT_TOKEN_NOSHELL);
515  }
516  else
517  {
518  cmd.data = mutt_str_dup(tok->dptr);
519  }
520  *pc = '`';
521  pid = filter_create(cmd.data, NULL, &fp, NULL);
522  if (pid < 0)
523  {
524  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", cmd.data);
525  FREE(&cmd.data);
526  return -1;
527  }
528  FREE(&cmd.data);
529 
530  tok->dptr = pc + 1;
531 
532  /* read line */
533  struct Buffer expn = mutt_buffer_make(0);
534  expn.data = mutt_file_read_line(NULL, &expn.dsize, fp, NULL, 0);
535  mutt_file_fclose(&fp);
536  filter_wait(pid);
537 
538  /* if we got output, make a new string consisting of the shell output
539  * plus whatever else was left on the original line */
540  /* BUT: If this is inside a quoted string, directly add output to
541  * the token */
542  if (expn.data)
543  {
544  if (qc)
545  {
546  mutt_buffer_addstr(dest, expn.data);
547  }
548  else
549  {
550  struct Buffer *copy = mutt_buffer_pool_get();
551  mutt_buffer_fix_dptr(&expn);
552  mutt_buffer_copy(copy, &expn);
553  mutt_buffer_addstr(copy, tok->dptr);
554  mutt_buffer_copy(tok, copy);
555  tok->dptr = tok->data;
557  }
558  FREE(&expn.data);
559  }
560  }
561  else if ((ch == '$') && (!qc || (qc == '"')) &&
562  ((tok->dptr[0] == '{') || isalpha((unsigned char) tok->dptr[0])))
563  {
564  const char *env = NULL;
565  char *var = NULL;
566 
567  if (tok->dptr[0] == '{')
568  {
569  pc = strchr(tok->dptr, '}');
570  if (pc)
571  {
572  var = mutt_strn_dup(tok->dptr + 1, pc - (tok->dptr + 1));
573  tok->dptr = pc + 1;
574 
575  if ((flags & MUTT_TOKEN_NOSHELL))
576  {
577  mutt_buffer_addch(dest, ch);
578  mutt_buffer_addch(dest, '{');
579  mutt_buffer_addstr(dest, var);
580  mutt_buffer_addch(dest, '}');
581  FREE(&var);
582  }
583  }
584  }
585  else
586  {
587  for (pc = tok->dptr; isalnum((unsigned char) *pc) || (pc[0] == '_'); pc++)
588  ; // do nothing
589 
590  var = mutt_strn_dup(tok->dptr, pc - tok->dptr);
591  tok->dptr = pc;
592  }
593  if (var)
594  {
595  struct Buffer result;
596  mutt_buffer_init(&result);
597  int rc = cs_subset_str_string_get(NeoMutt->sub, var, &result);
598 
599  if (CSR_RESULT(rc) == CSR_SUCCESS)
600  {
601  mutt_buffer_addstr(dest, result.data);
602  FREE(&result.data);
603  }
604  else if ((env = myvar_get(var)))
605  {
606  mutt_buffer_addstr(dest, env);
607  }
608  else if (!(flags & MUTT_TOKEN_NOSHELL) && (env = mutt_str_getenv(var)))
609  {
610  mutt_buffer_addstr(dest, env);
611  }
612  else
613  {
614  mutt_buffer_addch(dest, ch);
615  mutt_buffer_addstr(dest, var);
616  }
617  FREE(&var);
618  }
619  }
620  else
621  mutt_buffer_addch(dest, ch);
622  }
623  mutt_buffer_addch(dest, 0); /* terminate the string */
624  SKIPWS(tok->dptr);
625  return 0;
626 }
#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, int 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:394
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_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
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
+ Here is the call graph for this function:

◆ mutt_opts_free()

void mutt_opts_free ( void  )

clean up before quitting

Definition at line 631 of file init.c.

632 {
634 
635  alias_shutdown();
636 #ifdef USE_SIDEBAR
637  sb_shutdown();
638 #endif
639 
640  mutt_regexlist_free(&Alternates);
644  mutt_regexlist_free(&UnAlternates);
647 
651 
652  /* Lists of strings */
653  mutt_list_free(&AlternativeOrderList);
654  mutt_list_free(&AutoViewList);
655  mutt_list_free(&HeaderOrderList);
658  mutt_list_free(&MimeLookupList);
659  mutt_list_free(&Muttrc);
661  mutt_list_free(&UserHeader);
662 
663  /* Lists of AttachMatch */
668 
670 
672  FREE(&HomeDir);
673  FREE(&LastFolder);
675  FREE(&Username);
676 
679 
681 
682  mutt_hist_free();
683  mutt_keys_free();
684 
687 }
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:446
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:355
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:241
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:169
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 695 of file init.c.

696 {
697  struct Command *c = NULL;
698  for (size_t i = 0, size = mutt_commands_array(&c); i < size; i++)
699  {
700  if (((c[i].parse == mutt_parse_hook) || (c[i].parse == mutt_parse_idxfmt_hook)) &&
701  mutt_istr_equal(c[i].name, name))
702  {
703  return c[i].data;
704  }
705  }
706  return MUTT_HOOK_NO_FLAGS;
707 }
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 717 of file init.c.

718 {
719  int need_pause = 0;
720  int rc = 1;
721  struct Buffer err = mutt_buffer_make(256);
722  struct Buffer buf = mutt_buffer_make(256);
723 
725  alias_init();
727 #ifdef USE_COMP_MBOX
728  mutt_comp_init();
729 #endif
730 #ifdef USE_IMAP
731  imap_init();
732 #endif
733 #ifdef USE_LUA
734  mutt_lua_init();
735 #endif
738 
739  mutt_menu_init();
740 #ifdef USE_SIDEBAR
741  sb_init();
742 #endif
743 #ifdef USE_NOTMUCH
744  nm_init();
745 #endif
746 
747  snprintf(AttachmentMarker, sizeof(AttachmentMarker), "\033]9;%" PRIu64 "\a", // Escape
748  mutt_rand64());
749 
750  snprintf(ProtectedHeaderMarker, sizeof(ProtectedHeaderMarker), "\033]8;%lld\a", // Escape
751  (long long) mutt_date_epoch());
752 
753  /* "$spoolfile" precedence: config file, environment */
754  const char *p = mutt_str_getenv("MAIL");
755  if (!p)
756  p = mutt_str_getenv("MAILDIR");
757  if (!p)
758  {
759 #ifdef HOMESPOOL
760  mutt_buffer_concat_path(&buf, NONULL(HomeDir), MAILPATH);
761 #else
762  mutt_buffer_concat_path(&buf, MAILPATH, NONULL(Username));
763 #endif
764  p = mutt_b2s(&buf);
765  }
766  cs_str_initial_set(cs, "spoolfile", p, NULL);
767  cs_str_reset(cs, "spoolfile", NULL);
768 
769  p = mutt_str_getenv("REPLYTO");
770  if (p)
771  {
772  struct Buffer token;
773 
774  mutt_buffer_printf(&buf, "Reply-To: %s", p);
775  mutt_buffer_init(&token);
776  parse_my_hdr(&token, &buf, 0, &err); /* adds to UserHeader */
777  FREE(&token.data);
778  }
779 
780  p = mutt_str_getenv("EMAIL");
781  if (p)
782  {
783  cs_str_initial_set(cs, "from", p, NULL);
784  cs_str_reset(cs, "from", NULL);
785  }
786 
787  /* "$mailcap_path" precedence: config file, environment, code */
788  const char *env_mc = mutt_str_getenv("MAILCAPS");
789  if (env_mc)
790  cs_str_string_set(cs, "mailcap_path", env_mc, NULL);
791 
792  /* "$tmpdir" precedence: config file, environment, code */
793  const char *env_tmp = mutt_str_getenv("TMPDIR");
794  if (env_tmp)
795  cs_str_string_set(cs, "tmpdir", env_tmp, NULL);
796 
797  /* "$visual", "$editor" precedence: config file, environment, code */
798  const char *env_ed = mutt_str_getenv("VISUAL");
799  if (!env_ed)
800  env_ed = mutt_str_getenv("EDITOR");
801  if (env_ed)
802  {
803  cs_str_string_set(cs, "editor", env_ed, NULL);
804  cs_str_string_set(cs, "visual", env_ed, NULL);
805  }
806 
808  cs_str_initial_set(cs, "charset", C_Charset, NULL);
810 
811  Matches = mutt_mem_calloc(MatchesListsize, sizeof(char *));
812 
814 
815 #ifdef HAVE_GETSID
816  /* Unset suspend by default if we're the session leader */
817  if (getsid(0) == getpid())
818  C_Suspend = false;
819 #endif
820 
821  /* RFC2368, "4. Unsafe headers"
822  * The creator of a mailto URL can't expect the resolver of a URL to
823  * understand more than the "subject" and "body" headers. Clients that
824  * resolve mailto URLs into mail messages should be able to correctly
825  * create RFC822-compliant mail messages using the "subject" and "body"
826  * headers. */
827  add_to_stailq(&MailToAllow, "body");
828  add_to_stailq(&MailToAllow, "subject");
829  /* Cc, In-Reply-To, and References help with not breaking threading on
830  * mailing lists, see https://github.com/neomutt/neomutt/issues/115 */
831  add_to_stailq(&MailToAllow, "cc");
832  add_to_stailq(&MailToAllow, "in-reply-to");
833  add_to_stailq(&MailToAllow, "references");
834 
835  if (STAILQ_EMPTY(&Muttrc))
836  {
837  const char *xdg_cfg_home = mutt_str_getenv("XDG_CONFIG_HOME");
838 
839  if (!xdg_cfg_home && HomeDir)
840  {
841  mutt_buffer_printf(&buf, "%s/.config", HomeDir);
842  xdg_cfg_home = mutt_b2s(&buf);
843  }
844 
845  char *config = find_cfg(HomeDir, xdg_cfg_home);
846  if (config)
847  {
848  mutt_list_insert_tail(&Muttrc, config);
849  }
850  }
851  else
852  {
853  struct ListNode *np = NULL;
854  STAILQ_FOREACH(np, &Muttrc, entries)
855  {
856  mutt_buffer_strcpy(&buf, np->data);
857  FREE(&np->data);
859  np->data = mutt_buffer_strdup(&buf);
860  if (access(np->data, F_OK))
861  {
862  mutt_perror(np->data);
863  goto done; // TEST10: neomutt -F missing
864  }
865  }
866  }
867 
868  if (!STAILQ_EMPTY(&Muttrc))
869  {
870  cs_str_string_set(cs, "alias_file", STAILQ_FIRST(&Muttrc)->data, NULL);
871  }
872 
873  /* Process the global rc file if it exists and the user hasn't explicitly
874  * requested not to via "-n". */
875  if (!skip_sys_rc)
876  {
877  do
878  {
880  break;
881 
882  mutt_buffer_printf(&buf, "%s/neomuttrc", SYSCONFDIR);
883  if (access(mutt_b2s(&buf), F_OK) == 0)
884  break;
885 
886  mutt_buffer_printf(&buf, "%s/Muttrc", SYSCONFDIR);
887  if (access(mutt_b2s(&buf), F_OK) == 0)
888  break;
889 
890  mutt_buffer_printf(&buf, "%s/neomuttrc", PKGDATADIR);
891  if (access(mutt_b2s(&buf), F_OK) == 0)
892  break;
893 
894  mutt_buffer_printf(&buf, "%s/Muttrc", PKGDATADIR);
895  } while (false);
896 
897  if (access(mutt_b2s(&buf), F_OK) == 0)
898  {
899  if (source_rc(mutt_b2s(&buf), &err) != 0)
900  {
901  mutt_error("%s", err.data);
902  need_pause = 1; // TEST11: neomutt (error in /etc/neomuttrc)
903  }
904  }
905  }
906 
907  /* Read the user's initialization file. */
908  struct ListNode *np = NULL;
909  STAILQ_FOREACH(np, &Muttrc, entries)
910  {
911  if (np->data)
912  {
913  if (source_rc(np->data, &err) != 0)
914  {
915  mutt_error("%s", err.data);
916  need_pause = 1; // TEST12: neomutt (error in ~/.neomuttrc)
917  }
918  }
919  }
920 
921  if (execute_commands(commands) != 0)
922  need_pause = 1; // TEST13: neomutt -e broken
923 
924  if (!get_hostname(cs))
925  goto done;
926 
927  if (!C_Realname)
928  {
929  struct passwd *pw = getpwuid(getuid());
930  if (pw)
931  {
932  char name[256];
933  C_Realname = mutt_str_dup(mutt_gecos_name(name, sizeof(name), pw));
934  }
935  }
936  cs_str_initial_set(cs, "realname", C_Realname, NULL);
937 
938  if (need_pause && !OptNoCurses)
939  {
941  if (mutt_any_key_to_continue(NULL) == 'q')
942  goto done; // TEST14: neomutt -e broken (press 'q')
943  }
944 
945  mutt_file_mkdir(C_Tmpdir, S_IRWXU);
946 
947  mutt_hist_init();
949 
950 #ifdef USE_NOTMUCH
951  if (C_VirtualSpoolfile)
952  {
953  /* Find the first virtual folder and open it */
954  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
956  struct MailboxNode *mp = STAILQ_FIRST(&ml);
957  if (mp)
958  cs_str_string_set(cs, "spoolfile", mailbox_path(mp->mailbox), NULL);
960  }
961 #endif
962  rc = 0;
963 
964 done:
965  mutt_buffer_dealloc(&err);
966  mutt_buffer_dealloc(&buf);
967  return rc;
968 }
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:203
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
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
#define mutt_b2s(buf)
Definition: buffer.h:41
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
Definition: muttlib.c:1700
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:1499
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 981 of file init.c.

983 {
984  if (mutt_buffer_len(line) == 0)
985  return 0;
986 
988 
989  mutt_buffer_reset(err);
990 
991  /* Read from the beginning of line->data */
992  line->dptr = line->data;
993 
994  SKIPWS(line->dptr);
995  while (*line->dptr)
996  {
997  if (*line->dptr == '#')
998  break; /* rest of line is a comment */
999  if (*line->dptr == ';')
1000  {
1001  line->dptr++;
1002  continue;
1003  }
1005 
1006  struct Command *cmd = NULL;
1007  size_t size = mutt_commands_array(&cmd);
1008  size_t i;
1009  for (i = 0; i < size; i++)
1010  {
1011  if (mutt_str_equal(token->data, cmd[i].name))
1012  {
1013  rc = cmd[i].parse(token, line, cmd[i].data, err);
1014  if (rc != MUTT_CMD_SUCCESS)
1015  { /* -1 Error, +1 Finish */
1016  goto finish; /* Propagate return code */
1017  }
1018  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) cmd);
1019  break; /* Continue with next command */
1020  }
1021  }
1022  if (i == size)
1023  {
1024  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1025  rc = MUTT_CMD_ERROR;
1026  break; /* Ignore the rest of the line */
1027  }
1028  }
1029 finish:
1030  return rc;
1031 }
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:394
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
#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 1039 of file init.c.

1040 {
1041  if (!line || (*line == '\0'))
1042  return MUTT_CMD_ERROR;
1043 
1044  struct Buffer *line_buffer = mutt_buffer_pool_get();
1045  struct Buffer *token = mutt_buffer_pool_get();
1046 
1047  mutt_buffer_strcpy(line_buffer, line);
1048 
1049  enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
1050 
1051  mutt_buffer_pool_release(&line_buffer);
1052  mutt_buffer_pool_release(&token);
1053  return rc;
1054 }
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:981
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 1063 of file init.c.

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

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

1309 {
1310  char *pt = buf;
1311  int spaces; /* keep track of the number of leading spaces on the line */
1312 
1313  if (!Context || !Context->mailbox->label_hash)
1314  return 0;
1315 
1316  SKIPWS(buf);
1317  spaces = buf - pt;
1318 
1319  /* first TAB. Collect all the matches */
1320  if (numtabs == 1)
1321  {
1322  struct HashElem *entry = NULL;
1323  struct HashWalkState state = { 0 };
1324 
1325  NumMatched = 0;
1326  mutt_str_copy(UserTyped, buf, sizeof(UserTyped));
1327  memset(Matches, 0, MatchesListsize);
1328  memset(Completed, 0, sizeof(Completed));
1329  while ((entry = mutt_hash_walk(Context->mailbox->label_hash, &state)))
1330  candidate(UserTyped, entry->key.strkey, Completed, sizeof(Completed));
1332  qsort(Matches, NumMatched, sizeof(char *), (sort_t) mutt_istr_cmp);
1334 
1335  /* All matches are stored. Longest non-ambiguous string is ""
1336  * i.e. don't change 'buf'. Fake successful return this time */
1337  if (UserTyped[0] == '\0')
1338  return 1;
1339  }
1340 
1341  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1342  return 0;
1343 
1344  /* NumMatched will _always_ be at least 1 since the initial
1345  * user-typed string is always stored */
1346  if ((numtabs == 1) && (NumMatched == 2))
1347  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1348  else if ((numtabs > 1) && (NumMatched > 2))
1349  {
1350  /* cycle through all the matches */
1351  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1352  }
1353 
1354  /* return the completed label */
1355  strncpy(buf, Completed, buflen - spaces);
1356 
1357  return 1;
1358 }
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 1372 of file init.c.

1373 {
1374  char *pt = buf;
1375  int spaces;
1376 
1377  SKIPWS(buf);
1378  spaces = buf - pt;
1379 
1380  pt = (char *) mutt_strn_rfind((char *) buf, pos, "tag:");
1381  if (pt)
1382  {
1383  pt += 4;
1384  if (numtabs == 1)
1385  {
1386  /* First TAB. Collect all the matches */
1388 
1389  /* All matches are stored. Longest non-ambiguous string is ""
1390  * i.e. don't change 'buf'. Fake successful return this time. */
1391  if (UserTyped[0] == '\0')
1392  return true;
1393  }
1394 
1395  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1396  return false;
1397 
1398  /* NumMatched will _always_ be at least 1 since the initial
1399  * user-typed string is always stored */
1400  if ((numtabs == 1) && (NumMatched == 2))
1401  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1402  else if ((numtabs > 1) && (NumMatched > 2))
1403  {
1404  /* cycle through all the matches */
1405  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1406  }
1407 
1408  /* return the completed query */
1409  strncpy(pt, Completed, buf + buflen - pt - spaces);
1410  }
1411  else
1412  return false;
1413 
1414  return true;
1415 }
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 1429 of file init.c.

1430 {
1431  if (!buf)
1432  return false;
1433 
1434  char *pt = buf;
1435 
1436  /* Only examine the last token */
1437  char *last_space = strrchr(buf, ' ');
1438  if (last_space)
1439  pt = (last_space + 1);
1440 
1441  /* Skip the +/- */
1442  if ((pt[0] == '+') || (pt[0] == '-'))
1443  pt++;
1444 
1445  if (numtabs == 1)
1446  {
1447  /* First TAB. Collect all the matches */
1449 
1450  /* All matches are stored. Longest non-ambiguous string is ""
1451  * i.e. don't change 'buf'. Fake successful return this time. */
1452  if (UserTyped[0] == '\0')
1453  return true;
1454  }
1455 
1456  if ((Completed[0] == '\0') && (UserTyped[0] != '\0'))
1457  return false;
1458 
1459  /* NumMatched will _always_ be at least 1 since the initial
1460  * user-typed string is always stored */
1461  if ((numtabs == 1) && (NumMatched == 2))
1462  snprintf(Completed, sizeof(Completed), "%s", Matches[0]);
1463  else if ((numtabs > 1) && (NumMatched > 2))
1464  {
1465  /* cycle through all the matches */
1466  snprintf(Completed, sizeof(Completed), "%s", Matches[(numtabs - 2) % NumMatched]);
1467  }
1468 
1469  /* return the completed query */
1470  strncpy(pt, Completed, buf + buflen - pt);
1471 
1472  return true;
1473 }
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 1482 of file init.c.

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