NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
setenv.c
Go to the documentation of this file.
1
30
36
37#include "config.h"
38#include <ctype.h>
39#include <stdbool.h>
40#include <stdio.h>
41#include <string.h>
42#include "mutt/lib.h"
43#include "config/lib.h"
44#include "core/lib.h"
45#include "gui/lib.h"
46#include "setenv.h"
47#include "pager/lib.h"
48#include "parse/lib.h"
49
53static int envlist_sort(const void *a, const void *b, void *sdata)
54{
55 return strcmp(*(const char **) a, *(const char **) b);
56}
57
67enum CommandResult parse_setenv(const struct Command *cmd, struct Buffer *line,
68 const struct ParseContext *pc, struct ParseError *pe)
69{
70 struct Buffer *err = pe->message;
71
72 struct Buffer *token = buf_pool_get();
73 struct Buffer *tempfile = NULL;
75
76 char **envp = NeoMutt->env;
77
78 bool query = false;
79 bool prefix = false;
80 bool unset = (cmd->id == CMD_UNSETENV);
81
82 if (!MoreArgs(line))
83 {
84 if (!StartupComplete)
85 {
86 buf_printf(err, _("%s: too few arguments"), cmd->name);
87 goto done;
88 }
89
90 tempfile = buf_pool_get();
91 buf_mktemp(tempfile);
92
93 FILE *fp_out = mutt_file_fopen(buf_string(tempfile), "w");
94 if (!fp_out)
95 {
96 // L10N: '%s' is the file name of the temporary file
97 buf_printf(err, _("Could not create temporary file %s"), buf_string(tempfile));
98 rc = MUTT_CMD_ERROR;
99 goto done;
100 }
101
102 int count = 0;
103 for (char **env = NeoMutt->env; *env; env++)
104 count++;
105
106 mutt_qsort_r(NeoMutt->env, count, sizeof(char *), envlist_sort, NULL);
107
108 for (char **env = NeoMutt->env; *env; env++)
109 fprintf(fp_out, "%s\n", *env);
110
111 mutt_file_fclose(&fp_out);
112
113 struct PagerData pdata = { 0 };
114 struct PagerView pview = { &pdata };
115
116 pdata.fname = buf_string(tempfile);
117
118 pview.banner = cmd->name;
120 pview.mode = PAGER_MODE_OTHER;
121
122 mutt_do_pager(&pview, NULL);
123
124 rc = MUTT_CMD_SUCCESS;
125 goto done;
126 }
127
128 if (*line->dptr == '?')
129 {
130 query = true;
131 prefix = true;
132
133 if (unset)
134 {
135 buf_printf(err, _("Can't query option with the '%s' command"), cmd->name);
136 goto done;
137 }
138
139 line->dptr++;
140 }
141
142 /* get variable name */
144
145 /* Validate variable name: must match [_a-zA-Z][_a-zA-Z0-9]* */
146 const char *name = buf_string(token);
147 if (!buf_is_empty(token))
148 {
149 /* First character must be a letter or underscore */
150 if (!isalpha(name[0]) && (name[0] != '_'))
151 {
152 buf_printf(err, _("%s: invalid variable name '%s'"), cmd->name, name);
153 goto done;
154 }
155 /* Subsequent characters must be letter, digit, or underscore */
156 for (size_t i = 1; name[i] != '\0'; i++)
157 {
158 if (!isalpha(name[i]) && !mutt_isdigit(name[i]) && (name[i] != '_'))
159 {
160 buf_printf(err, _("%s: invalid variable name '%s'"), cmd->name, name);
161 goto done;
162 }
163 }
164 }
165
166 if (*line->dptr == '?')
167 {
168 if (unset)
169 {
170 buf_printf(err, _("Can't query option with the '%s' command"), cmd->name);
171 goto done;
172 }
173
174 if (prefix)
175 {
176 buf_printf(err, _("Can't use a prefix when querying a variable"));
177 goto done;
178 }
179
180 query = true;
181 line->dptr++;
182 }
183
184 if (query)
185 {
186 bool found = false;
187 while (envp && *envp)
188 {
189 /* This will display all matches for "^QUERY" */
190 if (mutt_str_startswith(*envp, buf_string(token)))
191 {
192 if (!found)
193 {
194 mutt_endwin();
195 found = true;
196 }
197 puts(*envp);
198 }
199 envp++;
200 }
201
202 if (found)
203 {
205 rc = MUTT_CMD_SUCCESS;
206 goto done;
207 }
208
209 buf_printf(err, _("%s is unset"), buf_string(token));
210 goto done;
211 }
212
213 if (unset)
214 {
216 rc = MUTT_CMD_SUCCESS;
217 goto done;
218 }
219
220 /* set variable */
221
222 if (*line->dptr == '=')
223 {
224 line->dptr++;
225 SKIPWS(line->dptr);
226 }
227
228 if (!MoreArgs(line))
229 {
230 buf_printf(err, _("%s: too few arguments"), cmd->name);
231 goto done;
232 }
233
234 char *varname = mutt_str_dup(buf_string(token));
236 envlist_set(&NeoMutt->env, varname, buf_string(token), true);
237 FREE(&varname);
238
239 rc = MUTT_CMD_SUCCESS;
240
241done:
242 buf_pool_release(&token);
243 buf_pool_release(&tempfile);
244 return rc;
245}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ CMD_UNSETENV
:unsetenv
Definition command.h:143
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:40
@ 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
Convenience wrapper for the config headers.
bool StartupComplete
When the config has been read.
Definition address.c:11
Convenience wrapper for the core headers.
bool mutt_isdigit(int arg)
Wrapper for isdigit(3)
Definition ctype.c:66
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:173
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:151
int mutt_do_pager(struct PagerView *pview, struct Email *e)
Display some page-able text to the user (help or attachment)
Definition do_pager.c:122
bool envlist_set(char ***envp, const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition envlist.c:88
bool envlist_unset(char ***envp, const char *name)
Unset an environment variable.
Definition envlist.c:136
int parse_extract_token(struct Buffer *dest, struct Buffer *line, TokenFlags flags)
Extract one token from a string.
Definition extract.c:49
#define TOKEN_EQUAL
Treat '=' as a special.
Definition extract.h:46
#define MoreArgs(buf)
Definition extract.h:31
#define TOKEN_QUESTION
Treat '?' as a special.
Definition extract.h:55
#define TOKEN_NO_FLAGS
No flags are set.
Definition extract.h:45
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
enum CommandResult parse_setenv(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'setenv' and 'unsetenv' commands - Implements Command::parse() -.
Definition setenv.c:67
static int envlist_sort(const void *a, const void *b, void *sdata)
Compare two environment strings - Implements sort_t -.
Definition setenv.c:53
Convenience wrapper for the gui headers.
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:234
GUI display a file/email/help in a viewport with paging.
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition lib.h:62
@ PAGER_MODE_OTHER
Pager is invoked via 3rd path. Non-email content is likely to be shown.
Definition lib.h:142
Text parsing functions.
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
void mutt_qsort_r(void *base, size_t nmemb, size_t size, sort_t compar, void *sdata)
Sort an array, where the comparator has access to opaque data rather than requiring global variables.
Definition qsort_r.c:67
Parse Setenv Commands.
#define SKIPWS(ch)
Definition string2.h:52
String manipulation buffer.
Definition buffer.h:36
char * dptr
Current read/write position.
Definition buffer.h:38
const char * name
Name of the Command.
Definition command.h:159
enum CommandId id
ID of the Command.
Definition command.h:160
Container for Accounts, Notifications.
Definition neomutt.h:41
char ** env
Private copy of the environment variables.
Definition neomutt.h:58
Data to be displayed by PagerView.
Definition lib.h:161
const char * fname
Name of the file to read.
Definition lib.h:165
Paged view into some data.
Definition lib.h:172
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition lib.h:173
enum PagerMode mode
Pager mode.
Definition lib.h:174
PagerFlags flags
Additional settings to tweak pager's function.
Definition lib.h:175
const char * banner
Title to display in status bar.
Definition lib.h:176
Context for config parsing (history/backtrace)
Definition pcontext.h:34
Detailed error information from config parsing.
Definition perror.h:34
struct Buffer * message
Error message.
Definition perror.h:35
#define buf_mktemp(buf)
Definition tmp.h:33