NeoMutt  2020-08-21-74-g346364
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_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 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...
 
const struct Commandmutt_command_get (const char *s)
 Get a Command by its name. More...
 
void mutt_commands_apply (void *data, void(*application)(void *, const struct Command *))
 Run a callback function on every Command. 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 94 of file init.c.

95 {
96  if (current <= (MatchesListsize - 2))
97  return;
98 
99  int base_space = 512; // Enough space for all of the config items
100  int extra_space = MatchesListsize - base_space;
101  extra_space *= 2;
102  const int space = base_space + extra_space;
103  mutt_mem_realloc(&Matches, space * sizeof(char *));
104  memset(&Matches[current + 1], 0, space - current);
105  MatchesListsize = space;
106 }
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:81
static const char ** Matches
Definition: init.c:79
+ 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 117 of file init.c.

118 {
119  if (!dest || !user || !src)
120  return;
121 
122  if (strstr(src, user) != src)
123  return;
124 
126  Matches[NumMatched++] = src;
127  if (dest[0] == '\0')
128  mutt_str_copy(dest, src, dlen);
129  else
130  {
131  int l;
132  for (l = 0; src[l] && src[l] == dest[l]; l++)
133  ; // do nothing
134 
135  dest[l] = '\0';
136  }
137 }
static int NumMatched
Definition: init.c:77
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:94
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:79
+ 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 146 of file init.c.

147 {
148  int tag_count_1 = 0;
149  int tag_count_2 = 0;
150 
151  NumMatched = 0;
152  mutt_str_copy(UserTyped, pt, sizeof(UserTyped));
153  memset(Matches, 0, MatchesListsize);
154  memset(Completed, 0, sizeof(Completed));
155 
157 
158  /* Work out how many tags there are. */
159  if (nm_get_all_tags(Context->mailbox, NULL, &tag_count_1) || (tag_count_1 == 0))
160  goto done;
161 
162  /* Free the old list, if any. */
163  if (nm_tags)
164  {
165  for (int i = 0; nm_tags[i]; i++)
166  FREE(&nm_tags[i]);
167  FREE(&nm_tags);
168  }
169  /* Allocate a new list, with sentinel. */
170  nm_tags = mutt_mem_malloc((tag_count_1 + 1) * sizeof(char *));
171  nm_tags[tag_count_1] = NULL;
172 
173  /* Get all the tags. */
174  if (nm_get_all_tags(Context->mailbox, nm_tags, &tag_count_2) || (tag_count_1 != tag_count_2))
175  {
176  FREE(&nm_tags);
177  nm_tags = NULL;
179  return -1;
180  }
181 
182  /* Put them into the completion machinery. */
183  for (int num = 0; num < tag_count_1; num++)
184  {
185  candidate(UserTyped, nm_tags[num], Completed, sizeof(Completed));
186  }
187 
190 
191 done:
193  return 0;
194 }
The "current" mailbox.
Definition: context.h:38
static int NumMatched
Definition: init.c:77
static char ** nm_tags
Definition: init.c:85
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:78
static int MatchesListsize
Definition: init.c:81
static void matches_ensure_morespace(int current)
Allocate more space for auto-completion.
Definition: init.c:94
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:2101
static char UserTyped[1024]
Definition: init.c:75
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:79
#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:117
+ 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 203 of file init.c.

204 {
205  int rc = 0;
206  struct Buffer *err = mutt_buffer_pool_get();
207 
208  struct ListNode *np = NULL;
209  STAILQ_FOREACH(np, p, entries)
210  {
211  enum CommandResult rc2 = mutt_parse_rc_line(np->data, err);
212  if (rc2 == MUTT_CMD_ERROR)
213  mutt_error(_("Error in command line: %s"), mutt_b2s(err));
214  else if (rc2 == MUTT_CMD_WARNING)
215  mutt_warning(_("Warning in command line: %s"), mutt_b2s(err));
216 
217  if ((rc2 == MUTT_CMD_ERROR) || (rc2 == MUTT_CMD_WARNING))
218  {
220  return -1;
221  }
222  }
224 
225  return rc;
226 }
#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:33
Error: Can&#39;t help the user.
Definition: mutt_commands.h:35
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:1041
#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:36
#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 235 of file init.c.

236 {
237  const char *names[] = {
238  "neomuttrc",
239  "muttrc",
240  NULL,
241  };
242 
243  const char *locations[][2] = {
244  { xdg_cfg_home, "neomutt/" },
245  { xdg_cfg_home, "mutt/" },
246  { home, ".neomutt/" },
247  { home, ".mutt/" },
248  { home, "." },
249  { NULL, NULL },
250  };
251 
252  for (int i = 0; locations[i][0] || locations[i][1]; i++)
253  {
254  if (!locations[i][0])
255  continue;
256 
257  for (int j = 0; names[j]; j++)
258  {
259  char buf[256];
260 
261  snprintf(buf, sizeof(buf), "%s/%s%s", locations[i][0], locations[i][1], names[j]);
262  if (access(buf, F_OK) == 0)
263  return mutt_str_dup(buf);
264  }
265  }
266 
267  return NULL;
268 }
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 276 of file init.c.

277 {
278  char *mailname = NULL;
279  static const char *mn_files[] = { "/etc/mailname", "/etc/mail/mailname" };
280 
281  for (size_t i = 0; i < mutt_array_size(mn_files); i++)
282  {
283  FILE *fp = mutt_file_fopen(mn_files[i], "r");
284  if (!fp)
285  continue;
286 
287  size_t len = 0;
288  mailname = mutt_file_read_line(NULL, &len, fp, NULL, 0);
289  mutt_file_fclose(&fp);
290  if (mailname && *mailname)
291  break;
292 
293  FREE(&mailname);
294  }
295 
296  return mailname;
297 }
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 308 of file init.c.

309 {
310  char *str = NULL;
311  struct utsname utsname;
312 
313  if (C_Hostname)
314  {
315  str = C_Hostname;
316  }
317  else
318  {
319  /* The call to uname() shouldn't fail, but if it does, the system is horribly
320  * broken, and the system's networking configuration is in an unreliable
321  * state. We should bail. */
322  if ((uname(&utsname)) == -1)
323  {
324  mutt_perror(_("unable to determine nodename via uname()"));
325  return false; // TEST09: can't test
326  }
327 
328  str = utsname.nodename;
329  }
330 
331  /* some systems report the FQDN instead of just the hostname */
332  char *dot = strchr(str, '.');
333  if (dot)
334  ShortHostname = mutt_strn_dup(str, dot - str);
335  else
337 
338  if (!C_Hostname)
339  {
340  /* now get FQDN. Use configured domain first, DNS next, then uname */
341 #ifdef DOMAIN
342  /* we have a compile-time domain name, use that for C_Hostname */
344  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname), DOMAIN);
345 #else
346  C_Hostname = getmailname();
347  if (!C_Hostname)
348  {
349  struct Buffer *domain = mutt_buffer_pool_get();
350  if (getdnsdomainname(domain) == 0)
351  {
352  C_Hostname =
354  sprintf((char *) C_Hostname, "%s.%s", NONULL(ShortHostname), mutt_b2s(domain));
355  }
356  else
357  {
358  /* DNS failed, use the nodename. Whether or not the nodename had a '.'
359  * in it, we can use the nodename as the FQDN. On hosts where DNS is
360  * not being used, e.g. small network that relies on hosts files, a
361  * short host name is all that is required for SMTP to work correctly.
362  * It could be wrong, but we've done the best we can, at this point the
363  * onus is on the user to provide the correct hostname if the nodename
364  * won't work in their network. */
365  C_Hostname = mutt_str_dup(utsname.nodename);
366  }
367  mutt_buffer_pool_release(&domain);
368  }
369 #endif
370  }
371  if (C_Hostname)
372  cs_str_initial_set(cs, "hostname", C_Hostname, NULL);
373 
374  return true;
375 }
#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:276
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_command_get()

const struct Command* mutt_command_get ( const char *  s)

Get a Command by its name.

Parameters
sCommand string to lookup
Return values
ptrSuccess, Command
NULLError, no such command

Definition at line 383 of file init.c.

384 {
385  for (int i = 0; Commands[i].name; i++)
386  if (mutt_str_equal(s, Commands[i].name))
387  return &Commands[i];
388  return NULL;
389 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
const char * name
Name of the command.
Definition: mutt_commands.h:46
const struct Command Commands[]
Definition: mutt_commands.c:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_commands_apply()

void mutt_commands_apply ( void *  data,
void(*)(void *, const struct Command *)  application 
)

Run a callback function on every Command.

Parameters
dataData to pass to the callback function
applicationCallback function

This is used by Lua to expose all of NeoMutt's Commands.

Definition at line 399 of file init.c.

400 {
401  for (int i = 0; Commands[i].name; i++)
402  application(data, &Commands[i]);
403 }
const char * name
Name of the command.
Definition: mutt_commands.h:46
char * data
Pointer to data.
Definition: buffer.h:35
const struct Command Commands[]
Definition: mutt_commands.c:50
+ 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 414 of file init.c.

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

652 {
654 
655  alias_shutdown();
656 #ifdef USE_SIDEBAR
657  sb_shutdown();
658 #endif
659 
660  mutt_regexlist_free(&Alternates);
664  mutt_regexlist_free(&UnAlternates);
667 
671 
672  /* Lists of strings */
673  mutt_list_free(&AlternativeOrderList);
674  mutt_list_free(&AutoViewList);
675  mutt_list_free(&HeaderOrderList);
678  mutt_list_free(&MimeLookupList);
679  mutt_list_free(&Muttrc);
681  mutt_list_free(&UserHeader);
682 
683  /* Lists of AttachMatch */
688 
690 
692  FREE(&HomeDir);
693  FREE(&LastFolder);
695  FREE(&Username);
696 
699 
701 
702  mutt_hist_free();
703  mutt_keys_free();
704 
706 }
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:40
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:660
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:41
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:39
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:240
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:38
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 714 of file init.c.

715 {
716  for (const struct Command *c = Commands; c->name; c++)
717  {
718  if (((c->parse == mutt_parse_hook) || (c->parse == mutt_parse_idxfmt_hook)) &&
719  mutt_istr_equal(c->name, name))
720  {
721  return c->data;
722  }
723  }
724  return MUTT_HOOK_NO_FLAGS;
725 }
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:44
const char * name
Name of the command.
Definition: mutt_commands.h:46
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
const struct Command Commands[]
Definition: mutt_commands.c:50
+ 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 735 of file init.c.

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

988 {
989  if (mutt_buffer_len(line) == 0)
990  return 0;
991 
992  int i;
994 
995  mutt_buffer_reset(err);
996 
997  /* Read from the beginning of line->data */
998  line->dptr = line->data;
999 
1000  SKIPWS(line->dptr);
1001  while (*line->dptr)
1002  {
1003  if (*line->dptr == '#')
1004  break; /* rest of line is a comment */
1005  if (*line->dptr == ';')
1006  {
1007  line->dptr++;
1008  continue;
1009  }
1011  for (i = 0; Commands[i].name; i++)
1012  {
1013  if (mutt_str_equal(token->data, Commands[i].name))
1014  {
1015  rc = Commands[i].parse(token, line, Commands[i].data, err);
1016  if (rc != MUTT_CMD_SUCCESS)
1017  { /* -1 Error, +1 Finish */
1018  goto finish; /* Propagate return code */
1019  }
1020  notify_send(NeoMutt->notify, NT_COMMAND, i, (void *) &Commands[i]);
1021  break; /* Continue with next command */
1022  }
1023  }
1024  if (!Commands[i].name)
1025  {
1026  mutt_buffer_printf(err, _("%s: unknown command"), NONULL(token->data));
1027  rc = MUTT_CMD_ERROR;
1028  break; /* Ignore the rest of the line */
1029  }
1030  }
1031 finish:
1032  return rc;
1033 }
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
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:33
Error: Can&#39;t help the user.
Definition: mutt_commands.h:35
#define _(a)
Definition: message.h:28
const char * name
Name of the command.
Definition: mutt_commands.h:46
A Command has been executed, Command.
Definition: notify_type.h:36
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:56
#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:414
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:37
const struct Command Commands[]
Definition: mutt_commands.c:50
#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 1041 of file init.c.

1042 {
1043  if (!line || (*line == '\0'))
1044  return MUTT_CMD_ERROR;
1045 
1046  struct Buffer *line_buffer = mutt_buffer_pool_get();
1047  struct Buffer *token = mutt_buffer_pool_get();
1048 
1049  mutt_buffer_strcpy(line_buffer, line);
1050 
1051  enum CommandResult rc = mutt_parse_rc_buffer(line_buffer, token, err);
1052 
1053  mutt_buffer_pool_release(&line_buffer);
1054  mutt_buffer_pool_release(&token);
1055  return rc;
1056 }
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:33
Error: Can&#39;t help the user.
Definition: mutt_commands.h:35
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:986
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 1065 of file init.c.

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

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

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

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

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

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

◆ NumMatched

int NumMatched = 0
static

Definition at line 77 of file init.c.

◆ Completed

char Completed[256] = { 0 }
static

Definition at line 78 of file init.c.

◆ Matches

const char** Matches
static

Definition at line 79 of file init.c.

◆ MatchesListsize

int MatchesListsize = 512
static

Definition at line 81 of file init.c.

◆ nm_tags

char** nm_tags
static

Definition at line 85 of file init.c.