NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
source.h File Reference

Parse Source Commands. More...

#include "core/lib.h"
+ Include dependency graph for source.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

enum CommandResult parse_source (const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
 Parse the 'source' command - Implements Command::parse() -.
 
int source_rc (const char *rcfile_path, struct ParseContext *pc, struct ParseError *pe)
 Read an initialization file.
 
void source_stack_cleanup (void)
 Free memory from the stack used for the source command.
 
enum CommandResult parse_rc_line_cwd (const char *line, char *cwd, struct ParseContext *pc, struct ParseError *pe)
 Parse and run a muttrc line in a relative directory.
 
char * mutt_get_sourced_cwd (void)
 Get the current file path that is being parsed.
 

Detailed Description

Parse Source Commands.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file source.h.

Function Documentation

◆ source_rc()

int source_rc ( const char * rcfile_path,
struct ParseContext * pc,
struct ParseError * pe )

Read an initialization file.

Parameters
rcfile_pathPath to initialization file
pcParse Context
peParse Errors
Return values
<0NeoMutt should pause to let the user know

Definition at line 67 of file source.c.

68{
69 if (!rcfile_path || !pc || !pe)
70 return -1;
71
72 struct Buffer *err = pe->message;
73
74 int lineno = 0, rc = 0, warnings = 0;
75 enum CommandResult line_rc;
76 struct Buffer *linebuf = NULL;
77 char *line = NULL;
78 char *currentline = NULL;
79 char rcfile[PATH_MAX + 1] = { 0 };
80 size_t linelen = 0;
81 pid_t pid;
82
83 mutt_str_copy(rcfile, rcfile_path, sizeof(rcfile));
84
85 size_t rcfilelen = mutt_str_len(rcfile);
86 if (rcfilelen == 0)
87 return -1;
88
89 bool ispipe = rcfile[rcfilelen - 1] == '|';
90
91 if (!ispipe)
92 {
93 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
94 if (!mutt_path_to_absolute(rcfile, np ? NONULL(np->data) : ""))
95 {
96 mutt_error(_("Error: Can't build path of '%s'"), rcfile_path);
97 return -1;
98 }
99
100 STAILQ_FOREACH(np, &MuttrcStack, entries)
101 {
102 if (mutt_str_equal(np->data, rcfile))
103 {
104 break;
105 }
106 }
107 if (np)
108 {
109 mutt_error(_("Error: Cyclic sourcing of configuration file '%s'"), rcfile);
110 return -1;
111 }
112
114 }
115
116 mutt_debug(LL_DEBUG2, "Reading configuration file '%s'\n", rcfile);
117
118 FILE *fp = mutt_open_read(rcfile, &pid);
119 if (!fp)
120 {
121 buf_printf(err, "%s: %s", rcfile, strerror(errno));
122 return -1;
123 }
124
125 linebuf = buf_pool_get();
126
127 const char *const c_config_charset = cs_subset_string(NeoMutt->sub, "config_charset");
128 const char *const c_charset = cc_charset();
129 while ((line = mutt_file_read_line(line, &linelen, fp, &lineno, MUTT_RL_CONT)) != NULL)
130 {
131 const bool conv = c_config_charset && c_charset;
132 if (conv)
133 {
134 currentline = mutt_str_dup(line);
135 if (!currentline)
136 continue;
137 mutt_ch_convert_string(&currentline, c_config_charset, c_charset, MUTT_ICONV_NO_FLAGS);
138 }
139 else
140 {
141 currentline = line;
142 }
143
144 buf_strcpy(linebuf, currentline);
145
146 buf_reset(err);
147 line_rc = parse_rc_line(linebuf, pc, pe);
148 if (line_rc == MUTT_CMD_ERROR)
149 {
150 mutt_error("%s:%d: %s", rcfile, lineno, buf_string(err));
151 if (--rc < -MAX_ERRS)
152 {
153 if (conv)
154 FREE(&currentline);
155 break;
156 }
157 }
158 else if (line_rc == MUTT_CMD_WARNING)
159 {
160 /* Warning */
161 mutt_warning("%s:%d: %s", rcfile, lineno, buf_string(err));
162 warnings++;
163 }
164 else if (line_rc == MUTT_CMD_FINISH)
165 {
166 if (conv)
167 FREE(&currentline);
168 break; /* Found "finish" command */
169 }
170 else
171 {
172 if (rc < 0)
173 rc = -1;
174 }
175 if (conv)
176 FREE(&currentline);
177 }
178
179 FREE(&line);
180 mutt_file_fclose(&fp);
181 if (ispipe && (pid != -1))
182 {
183 int status = filter_wait(pid);
184 if (status != 0)
185 {
186 mutt_error(_("Command '%s' exited with status %d"), rcfile, status);
187 if (rc == 0)
188 rc = -1; // Set error code if not already set
189 }
190 }
191
192 if (rc)
193 {
194 /* the neomuttrc source keyword */
195 buf_reset(err);
196 buf_printf(err, (rc >= -MAX_ERRS) ? _("source: errors in %s") : _("source: reading aborted due to too many errors in %s"),
197 rcfile);
198 rc = -1;
199 }
200 else
201 {
202 /* Don't alias errors with warnings */
203 if (warnings > 0)
204 {
205 buf_printf(err, ngettext("source: %d warning in %s", "source: %d warnings in %s", warnings),
206 warnings, rcfile);
207 rc = -2;
208 }
209 }
210
211 if (!ispipe && !STAILQ_EMPTY(&MuttrcStack))
212 {
213 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
215 FREE(&np->data);
216 FREE(&np);
217 }
218
219 buf_pool_release(&linebuf);
220 return rc;
221}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:39
@ MUTT_CMD_FINISH
Finish: Stop processing this file.
Definition command.h:41
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
const char * cc_charset(void)
Get the cached value of $charset.
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition file.c:682
#define MUTT_RL_CONT
-continuation
Definition file.h:41
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_warning(...)
Definition logging2.h:92
#define mutt_error(...)
Definition logging2.h:94
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition list.c:46
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition charset.c:817
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition charset.h:66
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition filter.c:220
#define _(a)
Definition message.h:28
bool mutt_path_to_absolute(char *path, const char *reference)
Convert a relative path to its absolute form.
Definition path.c:333
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:662
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:500
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:583
#define PATH_MAX
Definition mutt.h:49
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Definition muttlib.c:644
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define STAILQ_REMOVE_HEAD(head, field)
Definition queue.h:461
#define STAILQ_FIRST(head)
Definition queue.h:388
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define STAILQ_EMPTY(head)
Definition queue.h:382
enum CommandResult parse_rc_line(struct Buffer *line, struct ParseContext *pc, struct ParseError *pe)
Parse a line of user config.
Definition rc.c:45
#define MAX_ERRS
Definition source.c:58
static struct ListHead MuttrcStack
LIFO designed to contain the list of config files that have been sourced and avoid cyclic sourcing.
Definition source.c:56
#define NONULL(x)
Definition string2.h:44
String manipulation buffer.
Definition buffer.h:36
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
struct Buffer * message
Error message.
Definition perror.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ source_stack_cleanup()

void source_stack_cleanup ( void )

Free memory from the stack used for the source command.

Definition at line 274 of file source.c.

275{
277}
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_rc_line_cwd()

enum CommandResult parse_rc_line_cwd ( const char * line,
char * cwd,
struct ParseContext * pc,
struct ParseError * pe )

Parse and run a muttrc line in a relative directory.

Parameters
lineLine to be parsed
cwdFile relative where to run the line
pcParse Context
peParse Errors
Return values
CommandResultResult e.g. MUTT_CMD_SUCCESS

Definition at line 287 of file source.c.

289{
290 if (!line || !cwd || !pc || !pe)
291 return MUTT_CMD_ERROR;
292
294
295 struct Buffer *buf = buf_pool_get();
296 buf_strcpy(buf, line);
297 enum CommandResult ret = parse_rc_line(buf, pc, pe);
298 buf_pool_release(&buf);
299
300 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
302 FREE(&np->data);
303 FREE(&np);
304
305 return ret;
306}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_sourced_cwd()

char * mutt_get_sourced_cwd ( void )

Get the current file path that is being parsed.

Return values
ptrFile path that is being parsed or cwd at runtime
Note
Caller is responsible for freeing returned string

Definition at line 314 of file source.c.

315{
316 struct ListNode *np = STAILQ_FIRST(&MuttrcStack);
317 if (np && np->data)
318 return mutt_str_dup(np->data);
319
320 // stack is empty, return our own dummy file relative to cwd
321 struct Buffer *cwd = buf_pool_get();
322 mutt_path_getcwd(cwd);
323 buf_addstr(cwd, "/dummy.rc");
324 char *ret = buf_strdup(cwd);
325 buf_pool_release(&cwd);
326 return ret;
327}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
const char * mutt_path_getcwd(struct Buffer *cwd)
Get the current working directory.
Definition path.c:476
+ Here is the call graph for this function:
+ Here is the caller graph for this function: