DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
cmd.c File Reference
#include "quakedef.h"
#include "thread.h"
+ Include dependency graph for cmd.c:

Go to the source code of this file.

Data Structures

struct  cmd_iter_t
 

Functions

void Cbuf_AddText (cmd_state_t *cmd, const char *text)
 
void Cbuf_Clear (cmd_buf_t *cbuf)
 Clears all command buffers.
 
void Cbuf_Execute (cmd_buf_t *cbuf)
 
static void Cbuf_Execute_Deferred (cmd_buf_t *cbuf)
 
void Cbuf_Frame (cmd_buf_t *cbuf)
 
static void Cbuf_Frame_Input (void)
 
void Cbuf_InsertText (cmd_state_t *cmd, const char *text)
 
static void Cbuf_LinkString (cmd_state_t *cmd, llist_t *head, cmd_input_t *existing, const char *text, qbool leavepending, unsigned int cmdsize)
 
void Cbuf_Lock (cmd_buf_t *cbuf)
 
static cmd_input_tCbuf_NodeGet (cmd_buf_t *cbuf, cmd_input_t *existing)
 
static void Cbuf_ParseText (cmd_state_t *cmd, llist_t *head, cmd_input_t *existing, const char *text, qbool allowpending)
 
void Cbuf_Unlock (cmd_buf_t *cbuf)
 
void Cmd_AddCommand (unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
 called by the init functions of other parts of the program to register commands and functions to call for them.
 
static cmd_state_tCmd_AddInterpreter (cmd_buf_t *cbuf, cvar_state_t *cvars, unsigned cvars_flagsmask, unsigned cmds_flagsmask, cmd_userdefined_t *userdefined)
 
static void Cmd_Alias_f (cmd_state_t *cmd)
 
static void Cmd_Apropos_f (cmd_state_t *cmd)
 
qbool Cmd_Callback (cmd_state_t *cmd, cmd_function_t *func)
 
int Cmd_CheckParm (cmd_state_t *cmd, const char *parm)
 Returns the position (1 to argc-1) in the command's argument list where the given parameter apears, or 0 if not present.
 
qbool Cmd_CL_Callback (cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src)
 
void Cmd_ClearCSQCCommands (cmd_state_t *cmd)
 
const char * Cmd_CompleteAlias (cmd_state_t *cmd, const char *partial)
 
const char ** Cmd_CompleteAliasBuildList (cmd_state_t *cmd, const char *partial)
 
int Cmd_CompleteAliasCountPossible (cmd_state_t *cmd, const char *partial)
 
void Cmd_CompleteAliasPrint (cmd_state_t *cmd, const char *partial)
 
const char ** Cmd_CompleteBuildList (cmd_state_t *cmd, const char *partial)
 
const char * Cmd_CompleteCommand (cmd_state_t *cmd, const char *partial)
 attempts to match a partial command for automatic command line completion returns NULL if nothing fits
 
void Cmd_CompleteCommandPrint (cmd_state_t *cmd, const char *partial)
 
int Cmd_CompleteCountPossible (cmd_state_t *cmd, const char *partial)
 
static void Cmd_Defer_f (cmd_state_t *cmd)
 
static void Cmd_Echo_f (cmd_state_t *cmd)
 
static void Cmd_Exec (cmd_state_t *cmd, const char *filename)
 
static void Cmd_Exec_f (cmd_state_t *cmd)
 
static void Cmd_ExecuteAlias (cmd_state_t *cmd, cmd_alias_t *alias)
 
void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex)
 Parses a single line of text into arguments and tries to execute it.
 
qbool Cmd_Exists (cmd_state_t *cmd, const char *cmd_name)
 used by the cvar code to check for cvar / command name overlap
 
static const char * Cmd_GetCvarValue (cmd_state_t *cmd, const char *var, size_t varlen, cmd_alias_t *alias)
 
static const char * Cmd_GetDirectCvarValue (cmd_state_t *cmd, const char *varname, cmd_alias_t *alias, qbool *is_multiple)
 
void Cmd_Init (void)
 Command execution takes a null terminated string, breaks it into tokens, then searches for a command or variable that matches the first token.
 
static void Cmd_List_f (cmd_state_t *cmd)
 
void Cmd_NoOperation_f (cmd_state_t *cmd)
 
void Cmd_PreprocessAndExecuteString (cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex)
 Like Cmd_ExecuteString, but with variable expansion.
 
static size_t Cmd_PreprocessString (cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmd_alias_t *alias)
 Cmd_PreprocessString.
 
qbool Cmd_QuoteString (char *out, size_t outlen, const char *in, const char *quoteset, qbool putquotes)
 quotes a string so that it can be used as a command argument again; quoteset is a string that contains one or more of ", \, $ and specifies the characters to be quoted (you usually want to either pass ""\" or ""\$").
 
void Cmd_RestoreInitState (void)
 Restores cvars, commands and aliases to their init values and deletes any that were added since init.
 
void Cmd_SaveInitState (void)
 called by Host_Init, this marks cvars, commands and aliases with their init values
 
void Cmd_Shutdown (void)
 
static void Cmd_StuffCmds_f (cmd_state_t *cmd)
 
qbool Cmd_SV_Callback (cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src)
 
static void Cmd_Toggle_f (cmd_state_t *cmd)
 
static void Cmd_TokenizeString (cmd_state_t *cmd, const char *text)
 
static void Cmd_UnAlias_f (cmd_state_t *cmd)
 
static void Cmd_Wait_f (cmd_state_t *cmd)
 

Variables

mempool_tcbuf_mempool
 
static cmd_iter_tcmd_iter_all
 
cmd_state_tcmd_local
 command interpreter for local commands injected by SVQC, CSQC, MQC, server or client engine code uses cmddefs_all
 
cmd_state_tcmd_serverfromclient
 command interpreter for server commands received over network from clients uses cmddefs_null
 
cmd_userdefined_t cmd_userdefined_all
 aliases and csqc functions
 
cmd_userdefined_t cmd_userdefined_null
 intentionally empty
 
qbool host_stuffcmdsrun = false
 
qbool prvm_runawaycheck
 
cvar_t sv_cheats
 

Function Documentation

◆ Cbuf_AddText()

void Cbuf_AddText ( cmd_state_t * cmd,
const char * text )

as new commands are generated from the console or keybindings, the text is added to the end of the command buffer.

Definition at line 264 of file cmd.c.

265{
266 size_t l = strlen(text);
267 cmd_buf_t *cbuf = cmd->cbuf;
268 llist_t llist = {&llist, &llist};
269
270 if (cbuf->size + l > cbuf->maxsize)
271 {
272 Con_Printf(CON_WARN "Cbuf_AddText: input too large, %luKB ought to be enough for anybody.\n", (unsigned long)(cbuf->maxsize / 1024));
273 return;
274 }
275
276 Cbuf_Lock(cbuf);
277
278 // If the string terminates but the (last) line doesn't, the node will be left in the pending state (to be continued).
279 Cbuf_ParseText(cmd, &llist, (List_Is_Empty(&cbuf->start) ? NULL : List_Entry(cbuf->start.prev, cmd_input_t, list)), text, true);
280 List_Splice_Tail(&llist, &cbuf->start);
281
282 Cbuf_Unlock(cbuf);
283}
void Cbuf_Unlock(cmd_buf_t *cbuf)
Definition cmd.c:50
static void Cbuf_ParseText(cmd_state_t *cmd, llist_t *head, cmd_input_t *existing, const char *text, qbool allowpending)
Definition cmd.c:210
void Cbuf_Lock(cmd_buf_t *cbuf)
Definition cmd.c:45
static void List_Splice_Tail(const llist_t *list, llist_t *head)
Definition com_list.h:409
#define List_Entry(ptr, type, member)
Definition com_list.h:44
static qbool List_Is_Empty(const llist_t *list)
Definition com_list.h:211
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_WARN
Definition console.h:101
float strlen(string s)
void cmd(string command,...)
#define NULL
Definition qtypes.h:12
size_t maxsize
Definition cmd.h:117
llist_t start
Definition cmd.h:113
size_t size
Definition cmd.h:118
struct llist_s * prev
Definition com_list.h:32

References Cbuf_Lock(), Cbuf_ParseText(), Cbuf_Unlock(), cmd(), Con_Printf(), CON_WARN, List_Entry, List_Is_Empty(), List_Splice_Tail(), cmd_buf_t::maxsize, NULL, llist_t::prev, cmd_buf_t::size, cmd_buf_t::start, and strlen().

Referenced by Cbuf_Execute_Deferred(), CL_FinishTimeDemo(), CL_SignonReply(), CL_VM_Parse_StuffCmd(), Curl_CheckCommandWhenDone(), Host_Init(), Key_Console(), Key_Event(), M_Demo_Key(), M_GameOptions_Key(), M_LanConfig_Key(), M_Load_Key(), M_Main_Key(), M_Menu_Options_Graphics_AdjustSliders(), M_Options_Key(), M_Reset_Key(), M_Save_Key(), M_ServerList_Key(), M_Setup_Key(), M_SinglePlayer_Key(), M_Transfusion_Episode_Key(), M_Transfusion_Skill_Key(), M_Video_Key(), VM_changelevel(), VM_coredump(), and VM_localcmd().

◆ Cbuf_Clear()

void Cbuf_Clear ( cmd_buf_t * cbuf)

Clears all command buffers.

Definition at line 436 of file cmd.c.

437{
438 while (!List_Is_Empty(&cbuf->start))
439 List_Move_Tail(cbuf->start.next, &cbuf->free);
440 while (!List_Is_Empty(&cbuf->deferred))
441 List_Move_Tail(cbuf->deferred.next, &cbuf->free);
442 cbuf->size = 0;
443}
static void List_Move_Tail(llist_t *list, llist_t *head)
Definition com_list.h:336
llist_t deferred
Definition cmd.h:114
llist_t free
Definition cmd.h:115
struct llist_s * next
Definition com_list.h:33

References cmd_buf_t::deferred, cmd_buf_t::free, List_Is_Empty(), List_Move_Tail(), llist_t::next, cmd_buf_t::size, and cmd_buf_t::start.

Referenced by Cbuf_Execute(), Host_Error(), and MVM_error_cmd().

◆ Cbuf_Execute()

void Cbuf_Execute ( cmd_buf_t * cbuf)

Pulls off terminated lines of text from the command buffer and sends them through Cmd_ExecuteString. Stops when the buffer is empty. Normally called once per frame, but may be explicitly invoked.

Note
Do not call inside a command function!

Definition at line 351 of file cmd.c.

352{
353 cmd_input_t *current;
354 unsigned int i = 0;
355
356 // LadyHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
357 cbuf->tokenizebufferpos = 0;
358
359 while (!List_Is_Empty(&cbuf->start))
360 {
361 /*
362 * Delete the text from the command buffer and move remaining
363 * commands down. This is necessary because commands (exec, alias)
364 * can insert data at the beginning of the text buffer
365 */
366 current = List_Entry(cbuf->start.next, cmd_input_t, list);
367
368 /*
369 * Assume we're rolling with the current command-line and
370 * always set this false because alias expansion or cbuf insertion
371 * without a newline may set this true, and cause weirdness.
372 */
373 current->pending = false;
374
375 Cmd_PreprocessAndExecuteString(current->source, current->text, current->length, src_local, false);
376 cbuf->size -= current->length;
377 // Recycle memory so using WASD doesn't cause a malloc and free
378 List_Move_Tail(&current->list, &cbuf->free);
379
380 if (cbuf->wait)
381 {
382 /*
383 * Skip out while text still remains in
384 * buffer, leaving it for next frame
385 */
386 cbuf->wait = false;
387 break;
388 }
389
390 if (++i == 1000000 && prvm_runawaycheck)
391 {
392 Con_Printf(CON_WARN "Cbuf_Execute: runaway loop counter hit limit of %d commands, clearing command buffers!\n", i);
393 Cbuf_Clear(cbuf);
394 }
395 }
396}
void Cbuf_Clear(cmd_buf_t *cbuf)
Clears all command buffers.
Definition cmd.c:436
qbool prvm_runawaycheck
Definition prvm_edict.c:60
void Cmd_PreprocessAndExecuteString(cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex)
Like Cmd_ExecuteString, but with variable expansion.
Definition cmd.c:1323
@ src_local
from the command buffer
Definition cmd.h:75
int i
qbool wait
Definition cmd.h:116
int tokenizebufferpos
Definition cmd.h:120
char * text
Definition cmd.h:162
size_t length
excludes \0 terminator
Definition cmd.h:161
qbool pending
Definition cmd.h:163
cmd_state_t * source
Definition cmd.h:158
llist_t list
Definition cmd.h:157

References Cbuf_Clear(), Cmd_PreprocessAndExecuteString(), Con_Printf(), CON_WARN, cmd_buf_t::free, i, cmd_input_t::length, cmd_input_t::list, List_Entry, List_Is_Empty(), List_Move_Tail(), llist_t::next, cmd_input_t::pending, prvm_runawaycheck, cmd_buf_t::size, cmd_input_t::source, src_local, cmd_buf_t::start, cmd_input_t::text, cmd_buf_t::tokenizebufferpos, and cmd_buf_t::wait.

Referenced by Cbuf_Frame(), CL_ReadDemoMessage(), and Host_Init().

◆ Cbuf_Execute_Deferred()

static void Cbuf_Execute_Deferred ( cmd_buf_t * cbuf)
static

Definition at line 320 of file cmd.c.

321{
322 cmd_input_t *current, *n;
323 vec_t eat;
324
325 if (host.realtime - cbuf->deferred_oldtime < 0 || host.realtime - cbuf->deferred_oldtime > 1800)
327 eat = host.realtime - cbuf->deferred_oldtime;
328 if (eat < 1.0/128.0)
329 return;
331
332 List_For_Each_Entry_Safe(current, n, &cbuf->deferred, cmd_input_t, list)
333 {
334 current->delay -= eat;
335 if(current->delay <= 0)
336 {
337 Cbuf_AddText(current->source, current->text); // parse deferred string and append its cmdstring(s)
338 List_Entry(cbuf->start.prev, cmd_input_t, list)->pending = false; // faster than div0-stable's Cbuf_AddText(";\n");
339 List_Move_Tail(&current->list, &cbuf->free); // make deferred string memory available for reuse
340 cbuf->size -= current->length;
341 }
342 }
343}
void Cbuf_AddText(cmd_state_t *cmd, const char *text)
Definition cmd.c:264
#define List_For_Each_Entry_Safe(pos, n, head, type, member)
Definition com_list.h:173
#define n(x, y)
host_static_t host
Definition host.c:41
float vec_t
Definition qtypes.h:68
double deferred_oldtime
Definition cmd.h:121
vec_t delay
Definition cmd.h:159
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
Definition host.h:46

References Cbuf_AddText(), cmd_buf_t::deferred, cmd_buf_t::deferred_oldtime, cmd_input_t::delay, cmd_buf_t::free, host, cmd_input_t::length, cmd_input_t::list, List_Entry, List_For_Each_Entry_Safe, List_Move_Tail(), n, llist_t::prev, host_static_t::realtime, cmd_buf_t::size, cmd_input_t::source, cmd_buf_t::start, and cmd_input_t::text.

Referenced by Cbuf_Frame().

◆ Cbuf_Frame()

void Cbuf_Frame ( cmd_buf_t * cbuf)

Performs deferred commands and runs Cbuf_Execute, called by Host_Frame

Definition at line 417 of file cmd.c.

418{
419 // check for commands typed to the host
421
422// R_TimeReport("preconsole");
423
424 // execute commands queued with the defer command
426 if (cbuf->size)
427 {
429 Cbuf_Execute(cbuf);
431 }
432
433// R_TimeReport("console");
434}
static void Cbuf_Frame_Input(void)
Definition cmd.c:405
static void Cbuf_Execute_Deferred(cmd_buf_t *cbuf)
Definition cmd.c:320
void Cbuf_Execute(cmd_buf_t *cbuf)
Definition cmd.c:351
#define SV_LockThreadMutex()
Definition server.h:606
#define SV_UnlockThreadMutex()
Definition server.h:607

References Cbuf_Execute(), Cbuf_Execute_Deferred(), Cbuf_Frame_Input(), cmd_buf_t::size, SV_LockThreadMutex, and SV_UnlockThreadMutex.

Referenced by Host_Frame().

◆ Cbuf_Frame_Input()

static void Cbuf_Frame_Input ( void )
static

Definition at line 405 of file cmd.c.

406{
407 char *line;
408
409 if ((line = Sys_ConsoleInput()))
410 {
411 // bones_was_here: prepending allows a loop such as `alias foo "bar; wait; foo"; foo`
412 // to be broken with an alias or unalias command
414 }
415}
void Cbuf_InsertText(cmd_state_t *cmd, const char *text)
Definition cmd.c:292
cmd_state_t * cmd_local
command interpreter for local commands injected by SVQC, CSQC, MQC, server or client engine code uses...
Definition cmd.c:25
char * Sys_ConsoleInput(void)
Reads a line from POSIX stdin or the Windows console.
Definition sys_shared.c:667

References Cbuf_InsertText(), cmd_local, and Sys_ConsoleInput().

Referenced by Cbuf_Frame().

◆ Cbuf_InsertText()

void Cbuf_InsertText ( cmd_state_t * cmd,
const char * text )

when a command wants to issue other commands immediately, the text is inserted at the beginning of the buffer, before any remaining unexecuted commands.

Definition at line 292 of file cmd.c.

293{
294 cmd_buf_t *cbuf = cmd->cbuf;
295 llist_t llist = {&llist, &llist};
296 size_t l = strlen(text);
297
298 if (cbuf->size + l > cbuf->maxsize)
299 {
300 Con_Printf(CON_WARN "Cbuf_InsertText: input too large, %luKB ought to be enough for anybody.\n", (unsigned long)(cbuf->maxsize / 1024));
301 return;
302 }
303
304 Cbuf_Lock(cbuf);
305
306 // bones_was_here assertion: when prepending to the buffer it never makes sense to leave node(s) in the `pending` state,
307 // it would have been impossible to append to such text later in the old raw text buffer,
308 // and allowing it causes bugs when .cfg files lack \n at EOF (see: https://gitlab.com/xonotic/darkplaces/-/issues/378).
309 Cbuf_ParseText(cmd, &llist, (List_Is_Empty(&cbuf->start) ? NULL : List_Entry(cbuf->start.next, cmd_input_t, list)), text, false);
310 List_Splice(&llist, &cbuf->start);
311
312 Cbuf_Unlock(cbuf);
313}
static void List_Splice(const llist_t *list, llist_t *head)
Definition com_list.h:400

References Cbuf_Lock(), Cbuf_ParseText(), Cbuf_Unlock(), cmd(), Con_Printf(), CON_WARN, List_Entry, List_Is_Empty(), List_Splice(), cmd_buf_t::maxsize, llist_t::next, NULL, cmd_buf_t::size, cmd_buf_t::start, and strlen().

Referenced by Cbuf_Frame_Input(), CL_NextDemo(), Cmd_Exec(), Cmd_ExecuteAlias(), Cmd_StuffCmds_f(), FS_ChangeGameDirs(), Host_AddConfigText(), Key_Console(), Key_Event(), and M_Keys_Key().

◆ Cbuf_LinkString()

static void Cbuf_LinkString ( cmd_state_t * cmd,
llist_t * head,
cmd_input_t * existing,
const char * text,
qbool leavepending,
unsigned int cmdsize )
static

Definition at line 176 of file cmd.c.

177{
178 cmd_buf_t *cbuf = cmd->cbuf;
179 cmd_input_t *node = Cbuf_NodeGet(cbuf, existing);
180 unsigned int offset = node->length; // > 0 if(pending)
181
182 // node will match existing if its text was pending continuation
183 if(node != existing)
184 {
185 node->source = cmd;
186 List_Move_Tail(&node->list, head);
187 }
188
189 node->length += cmdsize;
190 if(node->size < node->length)
191 {
192 node->text = (char *)Mem_Realloc(cbuf_mempool, node->text, node->length + 1);
193 node->size = node->length;
194 }
195 cbuf->size += cmdsize;
196
197 dp_ustr2stp(&node->text[offset], node->length + 1, text, cmdsize);
198 //Con_Printf("^5Cbuf_LinkString(): %s `^7%s^5`\n", node->pending ? "append" : "new", &node->text[offset]);
199 node->pending = leavepending;
200}
mempool_t * cbuf_mempool
Definition cmd.c:38
static cmd_input_t * Cbuf_NodeGet(cmd_buf_t *cbuf, cmd_input_t *existing)
Definition cmd.c:149
char * dp_ustr2stp(char *dst, size_t dsize, const char *src, size_t slen)
Copies a measured byte sequence (unterminated string) to a null-terminated string.
Definition common.c:1388
GLuint GLuint GLintptr offset
Definition glquake.h:632
size_t size
excludes \0 terminator
Definition cmd.h:160
#define Mem_Realloc(pool, data, size)
Definition zone.h:94

References cbuf_mempool, Cbuf_NodeGet(), cmd(), dp_ustr2stp(), cmd_input_t::length, cmd_input_t::list, List_Move_Tail(), Mem_Realloc, offset, cmd_input_t::pending, cmd_buf_t::size, cmd_input_t::size, cmd_input_t::source, and cmd_input_t::text.

Referenced by Cbuf_ParseText(), and Cmd_Defer_f().

◆ Cbuf_Lock()

void Cbuf_Lock ( cmd_buf_t * cbuf)

Definition at line 45 of file cmd.c.

46{
48}
void * lock
Definition cmd.h:122
#define Thread_LockMutex(m)
Definition thread.h:17

References cmd_buf_t::lock, and Thread_LockMutex.

Referenced by Cbuf_AddText(), Cbuf_InsertText(), Cmd_Defer_f(), and Cmd_ExecuteString().

◆ Cbuf_NodeGet()

static cmd_input_t * Cbuf_NodeGet ( cmd_buf_t * cbuf,
cmd_input_t * existing )
static

Definition at line 149 of file cmd.c.

150{
151 cmd_input_t *node;
152 if(existing && existing->pending)
153 node = existing;
154 else if(!List_Is_Empty(&cbuf->free))
155 {
156 node = List_Entry(cbuf->free.next, cmd_input_t, list);
157 node->length = node->pending = 0;
158 }
159 else
160 {
161 node = (cmd_input_t *)Mem_Alloc(cbuf_mempool, sizeof(cmd_input_t));
162 node->list.prev = node->list.next = &node->list;
163 node->size = node->length = node->pending = 0;
164 }
165 return node;
166}
#define Mem_Alloc(pool, size)
Definition zone.h:92

References cbuf_mempool, cmd_buf_t::free, cmd_input_t::length, cmd_input_t::list, List_Entry, List_Is_Empty(), Mem_Alloc, llist_t::next, cmd_input_t::pending, llist_t::prev, and cmd_input_t::size.

Referenced by Cbuf_LinkString().

◆ Cbuf_ParseText()

static void Cbuf_ParseText ( cmd_state_t * cmd,
llist_t * head,
cmd_input_t * existing,
const char * text,
qbool allowpending )
static

Definition at line 210 of file cmd.c.

211{
212 unsigned int cmdsize = 0, start = 0, pos;
213 qbool quotes = false, comment = false;
214
215 for (pos = 0; text[pos]; ++pos)
216 {
217 switch(text[pos])
218 {
219 case ';':
220 if (comment || quotes)
221 break;
222 case '\r':
223 case '\n':
224 comment = false;
225 quotes = false; // matches div0-stable
226 if (cmdsize)
227 {
228 Cbuf_LinkString(cmd, head, existing, &text[start], false, cmdsize);
229 cmdsize = 0;
230 }
231 else if (existing && existing->pending) // all I got was this lousy \n
232 existing->pending = false;
233 continue; // don't increment cmdsize
234
235 case '/':
236 if (!quotes && text[pos + 1] == '/' && (pos == 0 || ISWHITESPACE(text[pos - 1])))
237 comment = true;
238 break;
239 case '"':
240 if (!comment && (pos == 0 || text[pos - 1] != '\\'))
241 quotes = !quotes;
242 break;
243 }
244
245 if (!comment)
246 {
247 if (!cmdsize)
248 start = pos;
249 ++cmdsize;
250 }
251 }
252
253 if (cmdsize) // the line didn't end yet but we do have a string
254 Cbuf_LinkString(cmd, head, existing, &text[start], allowpending, cmdsize);
255}
static void Cbuf_LinkString(cmd_state_t *cmd, llist_t *head, cmd_input_t *existing, const char *text, qbool leavepending, unsigned int cmdsize)
Definition cmd.c:176
#define ISWHITESPACE(ch)
Definition qdefs.h:184
bool qbool
Definition qtypes.h:9

References Cbuf_LinkString(), cmd(), ISWHITESPACE, and cmd_input_t::pending.

Referenced by Cbuf_AddText(), and Cbuf_InsertText().

◆ Cbuf_Unlock()

void Cbuf_Unlock ( cmd_buf_t * cbuf)

Definition at line 50 of file cmd.c.

51{
53}
#define Thread_UnlockMutex(m)
Definition thread.h:18

References cmd_buf_t::lock, and Thread_UnlockMutex.

Referenced by Cbuf_AddText(), Cbuf_InsertText(), Cmd_Defer_f(), Cmd_ExecuteString(), and Cmd_Shutdown().

◆ Cmd_AddCommand()

void Cmd_AddCommand ( unsigned flags,
const char * cmd_name,
xcommand_t function,
const char * description )

called by the init functions of other parts of the program to register commands and functions to call for them.

The cmd_name is referenced later, so it should not be in temp memory

Definition at line 1661 of file cmd.c.

1662{
1663 cmd_function_t *func;
1664 cmd_function_t *prev, *current;
1666 int i;
1667
1668 for (i = 0; i < 2; i++)
1669 {
1670 cmd = cmd_iter_all[i].cmd;
1671 if (flags & cmd->cmd_flagsmask)
1672 {
1673 // fail if the command is a variable name
1674 if (Cvar_FindVar(cmd->cvars, cmd_name, ~0))
1675 {
1676 Con_Printf(CON_WARN "Cmd_AddCommand: %s already defined as a var\n", cmd_name);
1677 return;
1678 }
1679
1680 if (function)
1681 {
1682 // fail if the command already exists in this interpreter
1683 for (func = cmd->engine_functions; func; func = func->next)
1684 {
1685 if (!strcmp(cmd_name, func->name))
1686 {
1687 Con_Printf(CON_WARN "Cmd_AddCommand: %s already defined\n", cmd_name);
1688 continue;
1689 }
1690 }
1691
1692 func = (cmd_function_t *)Mem_Alloc(cmd->mempool, sizeof(cmd_function_t));
1693 func->flags = flags;
1694 func->name = cmd_name;
1695 func->function = function;
1696 func->description = description;
1697 func->next = cmd->engine_functions;
1698
1699 // insert it at the right alphanumeric position
1700 for (prev = NULL, current = cmd->engine_functions; current && strcmp(current->name, func->name) < 0; prev = current, current = current->next)
1701 ;
1702 if (prev) {
1703 prev->next = func;
1704 }
1705 else {
1706 cmd->engine_functions = func;
1707 }
1708 func->next = current;
1709 }
1710 else
1711 {
1712 // mark qcfunc if the function already exists in the qc_functions list
1713 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1714 {
1715 if (!strcmp(cmd_name, func->name))
1716 {
1717 func->qcfunc = true; //[515]: csqc
1718 continue;
1719 }
1720 }
1721
1722 func = (cmd_function_t *)Mem_Alloc(cmd->mempool, sizeof(cmd_function_t));
1723 func->flags = flags;
1724 func->name = cmd_name;
1725 func->function = function;
1726 func->description = description;
1727 func->qcfunc = true; //[515]: csqc
1728 func->next = cmd->userdefined->qc_functions;
1729
1730 // bones_was_here: if this QC command overrides an engine command, store its pointer
1731 // to avoid doing this search at invocation if QC declines to handle this command.
1732 for (cmd_function_t *f = cmd->engine_functions; f; f = f->next)
1733 {
1734 if (!strcmp(cmd_name, f->name))
1735 {
1736 Con_DPrintf("Adding QC override of engine command %s\n", cmd_name);
1737 func->overridden = f;
1738 break;
1739 }
1740 }
1741
1742 // insert it at the right alphanumeric position
1743 for (prev = NULL, current = cmd->userdefined->qc_functions; current && strcmp(current->name, func->name) < 0; prev = current, current = current->next)
1744 ;
1745 if (prev) {
1746 prev->next = func;
1747 }
1748 else {
1749 cmd->userdefined->qc_functions = func;
1750 }
1751 func->next = current;
1752 }
1753 }
1754 }
1755}
static cmd_iter_t * cmd_iter_all
Definition cmd.c:36
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
float flags
cvar_t * Cvar_FindVar(cvar_state_t *cvars, const char *var_name, unsigned neededflags)
Definition cvar.c:36
float f
struct cmd_function_s * overridden
the engine cmd overriden by this QC cmd, if applicable
Definition cmd.h:95
const char * name
Definition cmd.h:91
struct cmd_function_s * next
Definition cmd.h:90
qbool qcfunc
Definition cmd.h:94
unsigned flags
Definition cmd.h:89
const char * description
Definition cmd.h:92
xcommand_t function
Definition cmd.h:93
cmd_state_t * cmd
Definition cmd.c:32
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127

References cmd(), cmd_iter_t::cmd, cmd_iter_all, Con_DPrintf(), Con_Printf(), CON_WARN, Cvar_FindVar(), cmd_function_t::description, f, cmd_function_t::flags, flags, cmd_function_t::function, i, Mem_Alloc, cmd_function_t::name, cmd_function_t::next, NULL, cmd_function_t::overridden, and cmd_function_t::qcfunc.

Referenced by CDAudio_Init(), CL_Demo_Init(), CL_Init(), CL_InitCommands(), CL_InitInput(), CL_Parse_Init(), CL_Particles_Init(), CL_Screen_Init(), CL_Video_Init(), Cmd_Init(), Con_Init(), Crypto_Init_Commands(), Curl_Init_Commands(), FS_Init_Commands(), gl_backend_init(), GL_Draw_Init(), GL_Main_Init(), GL_Surf_Init(), Host_InitLocal(), Key_Init(), M_Init(), Memory_Init_Commands(), Mod_Init(), MR_Init_Commands(), NetConn_Init(), PRVM_Init(), R_Modules_Init(), R_Shadow_EditLights_Init(), R_Sky_Init(), R_Textures_Init(), S_Init(), Sbar_Init(), SV_Init(), SV_InitOperatorCommands(), Sys_EM_Register_Commands(), V_Init(), VID_Shared_Init(), VM_CL_registercmd(), VM_M_registercommand(), and VM_SV_registercommand().

◆ Cmd_AddInterpreter()

static cmd_state_t * Cmd_AddInterpreter ( cmd_buf_t * cbuf,
cvar_state_t * cvars,
unsigned cvars_flagsmask,
unsigned cmds_flagsmask,
cmd_userdefined_t * userdefined )
static

Definition at line 1470 of file cmd.c.

1471{
1473
1474 cmd->mempool = Mem_AllocPool("commands", 0, NULL);
1475 // space for commands and script files
1476 cmd->cbuf = cbuf;
1477 cmd->null_string = "";
1478
1479 cmd->cvars = cvars;
1480 cmd->cvars_flagsmask = cvars_flagsmask;
1481 cmd->cmd_flagsmask = cmds_flagsmask;
1482 cmd->userdefined = userdefined;
1483
1484 return cmd;
1485}
struct mempool_s * mempool
Definition cmd.h:128
mempool_t * tempmempool
Definition zone.c:794
#define Mem_AllocPool(name, flags, parent)
Definition zone.h:104

References cmd(), Mem_Alloc, Mem_AllocPool, cmd_state_t::mempool, NULL, and tempmempool.

Referenced by Cmd_Init().

◆ Cmd_Alias_f()

static void Cmd_Alias_f ( cmd_state_t * cmd)
static

Definition at line 813 of file cmd.c.

814{
815 cmd_alias_t *a;
816 char line[MAX_INPUTLINE];
817 int i, c;
818 const char *s;
819 size_t alloclen;
820
821 if (Cmd_Argc(cmd) == 1)
822 {
823 Con_Print("Current alias commands:\n");
824 for (a = cmd->userdefined->alias ; a ; a=a->next)
825 Con_Printf("%s : %s", a->name, a->value);
826 return;
827 }
828
829 s = Cmd_Argv(cmd, 1);
830 if (strlen(s) >= MAX_ALIAS_NAME)
831 {
832 Con_Print(CON_WARN "Alias name is too long\n");
833 return;
834 }
835
836 // if the alias already exists, reuse it
837 for (a = cmd->userdefined->alias ; a ; a=a->next)
838 {
839 if (!strcmp(s, a->name))
840 {
841 Z_Free (a->value);
842 break;
843 }
844 }
845
846 if (!a)
847 {
848 cmd_alias_t *prev, *current;
849
850 a = (cmd_alias_t *)Z_Malloc (sizeof(cmd_alias_t));
851 dp_strlcpy (a->name, s, sizeof (a->name));
852 // insert it at the right alphanumeric position
853 for( prev = NULL, current = cmd->userdefined->alias ; current && strcmp( current->name, a->name ) < 0 ; prev = current, current = current->next )
854 ;
855 if( prev ) {
856 prev->next = a;
857 } else {
858 cmd->userdefined->alias = a;
859 }
860 a->next = current;
861 }
862
863
864// copy the rest of the command line
865 line[0] = 0; // start out with a null string
866 c = Cmd_Argc(cmd);
867 for (i=2 ; i < c ; i++)
868 {
869 if (i != 2)
870 dp_strlcat (line, " ", sizeof (line));
871 dp_strlcat (line, Cmd_Argv(cmd, i), sizeof (line));
872 }
873 dp_strlcat (line, "\n", sizeof (line));
874
875 alloclen = strlen (line) + 1;
876 if(alloclen >= 2)
877 line[alloclen - 2] = '\n'; // to make sure a newline is appended even if too long
878 a->value = (char *)Z_Malloc (alloclen);
879 memcpy (a->value, line, alloclen);
880}
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
#define dp_strlcat(dst, src, dsize)
Definition common.h:304
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
#define MAX_ALIAS_NAME
Definition qdefs.h:99
ret a
struct cmd_alias_s * next
Definition cmd.h:80
char name[MAX_ALIAS_NAME]
Definition cmd.h:81
#define Z_Malloc(size)
Definition zone.h:161
#define Z_Free(data)
Definition zone.h:164

References a, cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), CON_WARN, dp_strlcat, dp_strlcpy, i, MAX_ALIAS_NAME, MAX_INPUTLINE, cmd_alias_t::name, cmd_alias_t::next, NULL, strlen(), Z_Free, and Z_Malloc.

Referenced by Cmd_Init().

◆ Cmd_Apropos_f()

static void Cmd_Apropos_f ( cmd_state_t * cmd)
static

Definition at line 1400 of file cmd.c.

1401{
1402 cmd_function_t *func;
1403 cvar_t *cvar;
1404 cmd_alias_t *alias;
1405 const char *partial;
1406 int count;
1407 qbool ispattern;
1408 char vabuf[1024];
1409
1410 if (Cmd_Argc(cmd) > 1)
1411 partial = Cmd_Args(cmd);
1412 else
1413 {
1414 Con_Printf("usage: %s <string>\n",Cmd_Argv(cmd, 0));
1415 return;
1416 }
1417
1418 ispattern = partial && (strchr(partial, '*') || strchr(partial, '?'));
1419 if(!ispattern)
1420 partial = va(vabuf, sizeof(vabuf), "*%s*", partial);
1421
1422 count = 0;
1423 for (cvar = cmd->cvars->vars; cvar; cvar = cvar->next)
1424 {
1425 if (matchpattern_with_separator(cvar->name, partial, true, "", false) ||
1426 matchpattern_with_separator(cvar->description, partial, true, "", false))
1427 {
1428 Con_Printf ("cvar ");
1429 Cvar_PrintHelp(cvar, cvar->name, true);
1430 count++;
1431 }
1432 for (char **cvar_alias = cvar->aliases; cvar_alias && *cvar_alias; cvar_alias++)
1433 {
1434 if (matchpattern_with_separator(*cvar_alias, partial, true, "", false))
1435 {
1436 Con_Printf ("cvar ");
1437 Cvar_PrintHelp(cvar, *cvar_alias, true);
1438 count++;
1439 }
1440 }
1441 }
1442 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1443 {
1444 if (!matchpattern_with_separator(func->name, partial, true, "", false))
1445 if (!matchpattern_with_separator(func->description, partial, true, "", false))
1446 continue;
1447 Con_Printf("command ^2%s^7: %s\n", func->name, func->description);
1448 count++;
1449 }
1450 for (func = cmd->engine_functions; func; func = func->next)
1451 {
1452 if (!matchpattern_with_separator(func->name, partial, true, "", false))
1453 if (!matchpattern_with_separator(func->description, partial, true, "", false))
1454 continue;
1455 Con_Printf("command ^2%s^7: %s\n", func->name, func->description);
1456 count++;
1457 }
1458 for (alias = cmd->userdefined->alias; alias; alias = alias->next)
1459 {
1460 // procede here a bit differently as an alias value always got a final \n
1461 if (!matchpattern_with_separator(alias->name, partial, true, "", false))
1462 if (!matchpattern_with_separator(alias->value, partial, true, "\n", false)) // when \n is as separator wildcards don't match it
1463 continue;
1464 Con_Printf("alias ^5%s^7: %s", alias->name, alias->value); // do not print an extra \n
1465 count++;
1466 }
1467 Con_Printf("%i result%s\n\n", count, (count > 1) ? "s" : "");
1468}
static const char * Cmd_Args(cmd_state_t *cmd)
Definition cmd.h:260
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
void Cvar_PrintHelp(cvar_t *cvar, const char *name, qbool full)
Definition cvar.c:274
int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qbool wildcard_least_one)
Definition filematch.c:23
GLenum GLenum GLsizei count
Definition glquake.h:656
float cvar(string name)
char * value
Definition cmd.h:82
Definition cvar.h:66

References cmd(), Cmd_Argc(), Cmd_Args(), Cmd_Argv(), Con_Printf(), count, cvar(), Cvar_PrintHelp(), cmd_function_t::description, matchpattern_with_separator(), cmd_alias_t::name, cmd_function_t::name, cmd_alias_t::next, cmd_function_t::next, va(), and cmd_alias_t::value.

Referenced by Cmd_Init().

◆ Cmd_Callback()

qbool Cmd_Callback ( cmd_state_t * cmd,
cmd_function_t * func )

Definition at line 2008 of file cmd.c.

2009{
2010 if (func->function)
2011 func->function(cmd);
2012 else
2013 Con_Printf(CON_WARN "Command \"%s\" can not be executed\n", Cmd_Argv(cmd, 0));
2014 return true;
2015}

References cmd(), Cmd_Argv(), Con_Printf(), CON_WARN, and cmd_function_t::function.

Referenced by Cmd_CL_Callback().

◆ Cmd_CheckParm()

int Cmd_CheckParm ( cmd_state_t * cmd,
const char * parm )

Returns the position (1 to argc-1) in the command's argument list where the given parameter apears, or 0 if not present.

Definition at line 2140 of file cmd.c.

2141{
2142 int i;
2143
2144 if (!parm)
2145 {
2146 Con_Printf(CON_WARN "Cmd_CheckParm: NULL");
2147 return 0;
2148 }
2149
2150 for (i = 1; i < Cmd_Argc (cmd); i++)
2151 if (!strcasecmp (parm, Cmd_Argv(cmd, i)))
2152 return i;
2153
2154 return 0;
2155}

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), CON_WARN, and i.

◆ Cmd_CL_Callback()

qbool Cmd_CL_Callback ( cmd_state_t * cmd,
cmd_function_t * func,
const char * text,
size_t textlen,
cmd_source_t src )

Definition at line 2017 of file cmd.c.

2018{
2019 // TODO: Assign these functions to QC commands directly?
2020 if(func->qcfunc)
2021 {
2022 if(((func->flags & CF_CLIENT) && CL_VM_ConsoleCommand(text, textlen)) ||
2023 ((func->flags & CF_SERVER) && SV_VM_ConsoleCommand(text, textlen)))
2024 return true;
2025
2026 if (func->overridden) // If this QC command overrides an engine command,
2027 func = func->overridden; // fall back to that command.
2028 }
2029 if (func->flags & CF_SERVER_FROM_CLIENT)
2030 {
2032 {
2034 return true;
2035 }
2036 else if(!(func->flags & CF_SERVER))
2037 {
2038 Con_Printf(CON_WARN "Cannot execute client commands from a dedicated server console.\n");
2039 return true;
2040 }
2041 }
2042 return Cmd_Callback(cmd, func);
2043}
void CL_ForwardToServer_f(cmd_state_t *cmd)
adds the current command line as a clc_stringcmd to the client message.
Definition cl_cmd.c:174
qbool Cmd_Callback(cmd_state_t *cmd, cmd_function_t *func)
Definition cmd.c:2008
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
#define CF_SERVER_FROM_CLIENT
command the client is allowed to execute on the server as a stringcmd
Definition cmd.h:51
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
qbool CL_VM_ConsoleCommand(const char *text, size_t textlen)
Definition csprogs.c:573
cvar_t host_isclient
Definition host.c:61
qbool SV_VM_ConsoleCommand(const char *text, size_t textlen)
Definition svvm_cmds.c:2927
int integer
Definition cvar.h:73

References CF_CLIENT, CF_SERVER, CF_SERVER_FROM_CLIENT, CL_ForwardToServer_f(), CL_VM_ConsoleCommand(), cmd(), Cmd_Callback(), Con_Printf(), CON_WARN, cmd_function_t::flags, host_isclient, cvar_t::integer, cmd_function_t::overridden, cmd_function_t::qcfunc, and SV_VM_ConsoleCommand().

Referenced by Cmd_Init().

◆ Cmd_ClearCSQCCommands()

void Cmd_ClearCSQCCommands ( cmd_state_t * cmd)

Definition at line 1981 of file cmd.c.

1982{
1983 cmd_function_t *func;
1984 cmd_function_t **next = &cmd->userdefined->qc_functions;
1985
1986 while(*next)
1987 {
1988 func = *next;
1989 *next = func->next;
1990 Z_Free(func);
1991 }
1992}

References cmd(), cmd_function_t::next, and Z_Free.

Referenced by CL_VM_ShutDown().

◆ Cmd_CompleteAlias()

const char * Cmd_CompleteAlias ( cmd_state_t * cmd,
const char * partial )

Definition at line 1892 of file cmd.c.

1893{
1894 cmd_alias_t *alias;
1895 size_t len;
1896
1897 len = strlen(partial);
1898
1899 if (!len)
1900 return NULL;
1901
1902 // Check functions
1903 for (alias = cmd->userdefined->alias; alias; alias = alias->next)
1904 if (!strncasecmp(partial, alias->name, len))
1905 return alias->name;
1906
1907 return NULL;
1908}

References cmd(), cmd_alias_t::name, cmd_alias_t::next, NULL, and strlen().

◆ Cmd_CompleteAliasBuildList()

const char ** Cmd_CompleteAliasBuildList ( cmd_state_t * cmd,
const char * partial )

Definition at line 1961 of file cmd.c.

1962{
1963 cmd_alias_t *alias;
1964 size_t len = 0;
1965 size_t bpos = 0;
1966 size_t sizeofbuf = (Cmd_CompleteAliasCountPossible (cmd, partial) + 1) * sizeof (const char *);
1967 const char **buf;
1968
1969 len = strlen(partial);
1970 buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
1971 // Loop through the alias list and print all matches
1972 for (alias = cmd->userdefined->alias; alias; alias = alias->next)
1973 if (!strncasecmp(partial, alias->name, len))
1974 buf[bpos++] = alias->name;
1975
1976 buf[bpos] = NULL;
1977 return buf;
1978}
int Cmd_CompleteAliasCountPossible(cmd_state_t *cmd, const char *partial)
Definition cmd.c:1931
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657

References buf, cmd(), Cmd_CompleteAliasCountPossible(), Mem_Alloc, cmd_alias_t::name, cmd_alias_t::next, NULL, strlen(), and tempmempool.

Referenced by Con_CompleteCommandLine().

◆ Cmd_CompleteAliasCountPossible()

int Cmd_CompleteAliasCountPossible ( cmd_state_t * cmd,
const char * partial )

Definition at line 1931 of file cmd.c.

1932{
1933 cmd_alias_t *alias;
1934 size_t len;
1935 int h;
1936
1937 h = 0;
1938
1939 len = strlen(partial);
1940
1941 if (!len)
1942 return 0;
1943
1944 // Loop through the command list and count all partial matches
1945 for (alias = cmd->userdefined->alias; alias; alias = alias->next)
1946 if (!strncasecmp(partial, alias->name, len))
1947 h++;
1948
1949 return h;
1950}

References cmd(), cmd_alias_t::name, cmd_alias_t::next, and strlen().

Referenced by Cmd_CompleteAliasBuildList(), and Con_CompleteCommandLine().

◆ Cmd_CompleteAliasPrint()

void Cmd_CompleteAliasPrint ( cmd_state_t * cmd,
const char * partial )

Definition at line 1911 of file cmd.c.

1912{
1913 cmd_alias_t *alias;
1914 size_t len = strlen(partial);
1915 // Loop through the alias list and print all matches
1916 for (alias = cmd->userdefined->alias; alias; alias = alias->next)
1917 if (!strncasecmp(partial, alias->name, len))
1918 Con_Printf("^5%s^7: %s", alias->name, alias->value);
1919}

References cmd(), Con_Printf(), cmd_alias_t::name, cmd_alias_t::next, strlen(), and cmd_alias_t::value.

Referenced by Con_CompleteCommandLine().

◆ Cmd_CompleteBuildList()

const char ** Cmd_CompleteBuildList ( cmd_state_t * cmd,
const char * partial )

Definition at line 1847 of file cmd.c.

1848{
1849 cmd_function_t *func;
1850 size_t len = 0;
1851 size_t bpos = 0;
1852 size_t sizeofbuf = (Cmd_CompleteCountPossible (cmd, partial) + 1) * sizeof (const char *);
1853 const char **buf;
1854
1855 len = strlen(partial);
1856 buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
1857 // Loop through the functions lists and print all matches
1858 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1859 if (!strncasecmp(partial, func->name, len))
1860 buf[bpos++] = func->name;
1861 for (func = cmd->engine_functions; func; func = func->next)
1862 if (!strncasecmp(partial, func->name, len))
1863 buf[bpos++] = func->name;
1864
1865 buf[bpos] = NULL;
1866 return buf;
1867}
int Cmd_CompleteCountPossible(cmd_state_t *cmd, const char *partial)
Definition cmd.c:1814

References buf, cmd(), Cmd_CompleteCountPossible(), Mem_Alloc, cmd_function_t::name, cmd_function_t::next, NULL, strlen(), and tempmempool.

Referenced by Con_CompleteCommandLine().

◆ Cmd_CompleteCommand()

const char * Cmd_CompleteCommand ( cmd_state_t * cmd,
const char * partial )

attempts to match a partial command for automatic command line completion returns NULL if nothing fits

Definition at line 1783 of file cmd.c.

1784{
1785 cmd_function_t *func;
1786 size_t len;
1787
1788 len = strlen(partial);
1789
1790 if (!len)
1791 return NULL;
1792
1793// check functions
1794 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1795 if (!strncasecmp(partial, func->name, len))
1796 return func->name;
1797
1798 for (func = cmd->engine_functions; func; func = func->next)
1799 if (!strncasecmp(partial, func->name, len))
1800 return func->name;
1801
1802 return NULL;
1803}

References cmd(), cmd_function_t::name, cmd_function_t::next, NULL, and strlen().

◆ Cmd_CompleteCommandPrint()

void Cmd_CompleteCommandPrint ( cmd_state_t * cmd,
const char * partial )

Definition at line 1870 of file cmd.c.

1871{
1872 cmd_function_t *func;
1873 size_t len = strlen(partial);
1874 // Loop through the command list and print all matches
1875 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1876 if (!strncasecmp(partial, func->name, len))
1877 Con_Printf("^2%s^7: %s\n", func->name, func->description);
1878 for (func = cmd->engine_functions; func; func = func->next)
1879 if (!strncasecmp(partial, func->name, len))
1880 Con_Printf("^2%s^7: %s\n", func->name, func->description);
1881}

References cmd(), Con_Printf(), cmd_function_t::description, cmd_function_t::name, cmd_function_t::next, and strlen().

Referenced by Con_CompleteCommandLine().

◆ Cmd_CompleteCountPossible()

int Cmd_CompleteCountPossible ( cmd_state_t * cmd,
const char * partial )

Definition at line 1814 of file cmd.c.

1815{
1816 cmd_function_t *func;
1817 size_t len;
1818 int h;
1819
1820 h = 0;
1821 len = strlen(partial);
1822
1823 if (!len)
1824 return 0;
1825
1826 // Loop through the command list and count all partial matches
1827 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1828 if (!strncasecmp(partial, func->name, len))
1829 h++;
1830
1831 for (func = cmd->engine_functions; func; func = func->next)
1832 if (!strncasecmp(partial, func->name, len))
1833 h++;
1834
1835 return h;
1836}

References cmd(), cmd_function_t::name, cmd_function_t::next, and strlen().

Referenced by Cmd_CompleteBuildList(), and Con_CompleteCommandLine().

◆ Cmd_Defer_f()

static void Cmd_Defer_f ( cmd_state_t * cmd)
static

Definition at line 79 of file cmd.c.

80{
81 cmd_input_t *current;
82 cmd_buf_t *cbuf = cmd->cbuf;
83 unsigned int cmdsize;
84
85 if(Cmd_Argc(cmd) == 1)
86 {
87 if(List_Is_Empty(&cbuf->deferred))
88 Con_Printf("No commands are pending.\n");
89 else
90 {
91 List_For_Each_Entry(current, &cbuf->deferred, cmd_input_t, list)
92 Con_Printf("-> In %9.2f: %s\n", current->delay, current->text);
93 }
94 }
95 else if(Cmd_Argc(cmd) == 2 && !strcasecmp("clear", Cmd_Argv(cmd, 1)))
96 {
97 while(!List_Is_Empty(&cbuf->deferred))
98 {
99 cbuf->size -= List_Entry(cbuf->deferred.next, cmd_input_t, list)->length;
100 List_Move_Tail(cbuf->deferred.next, &cbuf->free);
101 }
102 }
103 else if(Cmd_Argc(cmd) == 3 && (cmdsize = strlen(Cmd_Argv(cmd, 2))) )
104 {
105 Cbuf_Lock(cbuf);
106
107 Cbuf_LinkString(cmd, &cbuf->deferred, NULL, Cmd_Argv(cmd, 2), false, cmdsize);
108 List_Entry(cbuf->deferred.prev, cmd_input_t, list)->delay = atof(Cmd_Argv(cmd, 1));
109
110 Cbuf_Unlock(cbuf);
111 }
112 else
113 {
114 Con_Printf("usage: defer <seconds> <command>\n"
115 " defer clear\n");
116 return;
117 }
118}
#define List_For_Each_Entry(pos, head, type, member)
Definition com_list.h:121

References Cbuf_LinkString(), Cbuf_Lock(), Cbuf_Unlock(), cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), cmd_buf_t::deferred, cmd_input_t::delay, cmd_buf_t::free, List_Entry, List_For_Each_Entry, List_Is_Empty(), List_Move_Tail(), llist_t::next, NULL, llist_t::prev, cmd_buf_t::size, strlen(), and cmd_input_t::text.

Referenced by Cmd_Init().

◆ Cmd_Echo_f()

static void Cmd_Echo_f ( cmd_state_t * cmd)
static

Definition at line 717 of file cmd.c.

718{
719 int i;
720
721 for (i=1 ; i<Cmd_Argc(cmd) ; i++)
722 Con_Printf("%s ",Cmd_Argv(cmd, i));
723 Con_Print("\n");
724}

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), and i.

Referenced by Cmd_Init().

◆ Cmd_Exec()

static void Cmd_Exec ( cmd_state_t * cmd,
const char * filename )
static

Definition at line 516 of file cmd.c.

517{
518 char *f;
519 size_t filenameLen = strlen(filename);
520 qbool isdefaultcfg =
521 !strcmp(filename, "default.cfg") ||
522 (filenameLen >= 12 && !strcmp(filename + filenameLen - 12, "/default.cfg"));
523
524 if (!strcmp(filename, "config.cfg"))
525 {
526 filename = CONFIGFILENAME;
527 if (Sys_CheckParm("-noconfig"))
528 return; // don't execute config.cfg
529 }
530
531 f = (char *)FS_LoadFile (filename, tempmempool, false, NULL);
532 if (!f)
533 {
534 Con_Printf(CON_WARN "couldn't exec %s\n",filename);
535 return;
536 }
537 Con_Printf("execing %s\n",filename);
538
539 // if executing default.cfg for the first time, lock the cvar defaults
540 // it may seem backwards to insert this text BEFORE the default.cfg
541 // but Cbuf_InsertText inserts before, so this actually ends up after it.
542 if (isdefaultcfg)
543 Cbuf_InsertText(cmd, "\ncvar_lockdefaults\n");
544
546 Mem_Free(f);
547
548 if (isdefaultcfg)
549 {
550 // special defaults for specific games go here, these execute before default.cfg
551 // and after gamegroup defaults (see below)
552 switch(gamemode)
553 {
554 case GAME_NEHAHRA:
555 Cbuf_InsertText(cmd, "\n"
556// Nehahra pushable crates malfunction in some levels if this is on
557"sv_gameplayfix_upwardvelocityclearsongroundflag 0\n"
558// Nehahra NPC AI is confused by blowupfallenzombies
559"sv_gameplayfix_blowupfallenzombies 0\n"
560 );
561 break;
562 case GAME_HIPNOTIC:
563 case GAME_QUOTH:
564 Cbuf_InsertText(cmd, "\n"
565// hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
566"sv_gameplayfix_blowupfallenzombies 0\n"
567// hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
568"sys_ticrate 0.02\n"
569// hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
570"sv_gameplayfix_slidemoveprojectiles 0\n"
571 );
572 break;
573 case GAME_ROGUE:
574 Cbuf_InsertText(cmd, "\n"
575// rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
576"sv_gameplayfix_blowupfallenzombies 0\n"
577// On r2m3 3 of the 4 monster_lava_man are placed in solid clips so droptofloor() moves them to a lower level if tracebox can
578// move them out of solid, if it can't they're stuck (original behaviour), only proper fix is to move them with a .ent file.
579"mod_q1bsp_traceoutofsolid 0\n"
580 );
581 break;
582 case GAME_TENEBRAE:
583 if (cls.state != ca_dedicated)
584 Cbuf_InsertText(cmd, "\n"
585"r_shadow_gloss 2\n"
586"r_shadow_bumpscale_basetexture 4\n"
587 );
588 break;
589 case GAME_NEXUIZ:
590 Cbuf_InsertText(cmd, "\n"
591"sv_gameplayfix_q2airaccelerate 1\n"
592"sv_gameplayfix_stepmultipletimes 1\n"
593 );
594 if (cls.state != ca_dedicated)
595 Cbuf_InsertText(cmd, "\n"
596"csqc_polygons_defaultmaterial_nocullface 1\n"
597"con_chatsound_team_mask 13\n"
598 );
599 break;
600 case GAME_XONOTIC:
602 Cbuf_InsertText(cmd, "\n"
603// compatibility for versions prior to 2020-05-25, this can be overridden in newer versions to get the default behavior and be consistent with FTEQW engine
604"sv_qcstats 1\n"
605"mod_q1bsp_zero_hullsize_cutoff 8.03125\n"
606 );
607 if (cls.state != ca_dedicated)
608 Cbuf_InsertText(cmd, "\n"
609"csqc_polygons_defaultmaterial_nocullface 1\n"
610"con_chatsound_team_mask 13\n"
611 );
612 break;
613 case GAME_STEELSTORM:
614 if (cls.state != ca_dedicated)
615 Cbuf_InsertText(cmd, "\n"
616// Steel Storm: Burning Retribution csqc misinterprets CSQC_InputEvent if type is a value other than 0 or 1
617"cl_csqc_generatemousemoveevents 0\n"
618"csqc_polygons_defaultmaterial_nocullface 1\n"
619 );
620 break;
621 case GAME_QUAKE15:
622 Cbuf_InsertText(cmd, "\n"
623// Corpses slide around without this bug from old DP versions
624"sv_gameplayfix_impactbeforeonground 1\n"
625// Reduce likelihood of incorrectly placed corpses sinking into the ground
626"sv_gameplayfix_unstickentities 1\n"
627 );
628 break;
629 case GAME_AD:
630 if (cls.state != ca_dedicated)
631 Cbuf_InsertText(cmd, "\n"
632// Arcane Dimensions V1.80 Patch 1 assumes engines that don't pass values to CSQC_Init() are DP,
633// instead of doing a workaround there we can give it what it really wants (fixes offscreen HUD).
634"csqc_lowres 1\n"
635 );
636 break;
637 case GAME_CTSJ2:
638 Cbuf_InsertText(cmd, "\n"
639// Doesn't completely initialise during worldspawn and the init frames, sometimes causing the
640// essential item on start.bsp to not spawn when the local client connects and spawns "too fast".
641"sv_init_frame_count 3\n"
642 );
643 default:
644 break;
645 }
646
647 // special defaults for game groups go here, these execute before the specific games above
648 switch (com_startupgamegroup)
649 {
650 case GAME_NORMAL: // id1 Quake and its mods
651 Cbuf_InsertText(cmd, "\n"
652"sv_gameplayfix_blowupfallenzombies 0\n"
653"sv_gameplayfix_findradiusdistancetobox 0\n"
654"sv_gameplayfix_grenadebouncedownslopes 0\n"
655"sv_gameplayfix_slidemoveprojectiles 0\n"
656"sv_gameplayfix_upwardvelocityclearsongroundflag 0\n"
657"sv_gameplayfix_setmodelrealbox 0\n"
658"sv_gameplayfix_droptofloorstartsolid 0\n"
659"sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 0\n"
660"sv_gameplayfix_noairborncorpse 0\n"
661"sv_gameplayfix_noairborncorpse_allowsuspendeditems 0\n"
662"sv_gameplayfix_easierwaterjump 0\n"
663"sv_gameplayfix_delayprojectiles 0\n"
664"sv_gameplayfix_multiplethinksperframe 0\n"
665"sv_gameplayfix_fixedcheckwatertransition 0\n"
666"sv_gameplayfix_q1bsptracelinereportstexture 0\n"
667"sv_gameplayfix_swiminbmodels 0\n"
668"sv_gameplayfix_downtracesupportsongroundflag 0\n"
669// Work around low brightness and poor legibility of Quake font
670"r_textbrightness 0.25\n"
671"r_textcontrast 1.25\n"
672 );
673 break;
674 default:
675 break;
676 }
677 }
678}
client_static_t cls
Definition cl_main.c:116
@ ca_dedicated
Definition client.h:530
gamemode_t gamemode
Definition com_game.c:26
gamemode_t com_startupgamegroup
Definition com_game.c:36
@ GAME_NEXUIZ
Definition com_game.h:33
@ GAME_QUOTH
Definition com_game.h:31
@ GAME_ROGUE
Definition com_game.h:30
@ GAME_STEELSTORM
added by motorsep
Definition com_game.h:53
@ GAME_VORETOURNAMENT
Definition com_game.h:60
@ GAME_QUAKE15
added by bones_was_here as it depends on an old bug and a workaround
Definition com_game.h:63
@ GAME_NEHAHRA
Definition com_game.h:32
@ GAME_NORMAL
Definition com_game.h:28
@ GAME_CTSJ2
added by bones_was_here as it has a race condition that requires a workaound
Definition com_game.h:65
@ GAME_TENEBRAE
full of evil hackery
Definition com_game.h:41
@ GAME_XONOTIC
Definition com_game.h:34
@ GAME_AD
added by bones_was_here as it depends on old DP behaviour or csqc_lowres
Definition com_game.h:64
@ GAME_HIPNOTIC
Definition com_game.h:29
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
#define CONFIGFILENAME
Definition quakedef.h:29
cactive_t state
Definition client.h:568
int Sys_CheckParm(const char *parm)
Definition sys_shared.c:327
#define Mem_Free(mem)
Definition zone.h:96

References ca_dedicated, Cbuf_InsertText(), cls, cmd(), com_startupgamegroup, Con_Printf(), CON_WARN, CONFIGFILENAME, f, FS_LoadFile(), GAME_AD, GAME_CTSJ2, GAME_HIPNOTIC, GAME_NEHAHRA, GAME_NEXUIZ, GAME_NORMAL, GAME_QUAKE15, GAME_QUOTH, GAME_ROGUE, GAME_STEELSTORM, GAME_TENEBRAE, GAME_VORETOURNAMENT, GAME_XONOTIC, gamemode, Mem_Free, NULL, client_static_t::state, strlen(), Sys_CheckParm(), and tempmempool.

Referenced by Cmd_Exec_f().

◆ Cmd_Exec_f()

static void Cmd_Exec_f ( cmd_state_t * cmd)
static

Definition at line 685 of file cmd.c.

686{
687 fssearch_t *s;
688 int i;
689
690 if (Cmd_Argc(cmd) != 2)
691 {
692 Con_Print("exec <filename> : execute a script file\n");
693 return;
694 }
695
696 s = FS_Search(Cmd_Argv(cmd, 1), true, true, NULL);
697 if(!s || !s->numfilenames)
698 {
699 Con_Printf(CON_WARN "couldn't exec %s\n",Cmd_Argv(cmd, 1));
700 return;
701 }
702
703 for(i = 0; i < s->numfilenames; ++i)
704 Cmd_Exec(cmd, s->filenames[i]);
705
706 FS_FreeSearch(s);
707}
static void Cmd_Exec(cmd_state_t *cmd, const char *filename)
Definition cmd.c:516
void FS_FreeSearch(fssearch_t *search)
Definition fs.c:3963
fssearch_t * FS_Search(const char *pattern, int caseinsensitive, int quiet, const char *packfile)
Definition fs.c:3756
char ** filenames
Definition fs.h:117
int numfilenames
Definition fs.h:116

References cmd(), Cmd_Argc(), Cmd_Argv(), Cmd_Exec(), Con_Print(), Con_Printf(), CON_WARN, fssearch_t::filenames, FS_FreeSearch(), FS_Search(), i, NULL, and fssearch_t::numfilenames.

Referenced by Cmd_Init().

◆ Cmd_ExecuteAlias()

static void Cmd_ExecuteAlias ( cmd_state_t * cmd,
cmd_alias_t * alias )
static

Definition at line 1306 of file cmd.c.

1307{
1308 static char buffer[ MAX_INPUTLINE ]; // cmd_mutex
1309 static char buffer2[ MAX_INPUTLINE ]; // cmd_mutex
1310 qbool ret = Cmd_PreprocessString( cmd, alias->value, buffer, sizeof(buffer) - 2, alias );
1311 if(!ret)
1312 return;
1313 // insert at start of command buffer, so that aliases execute in order
1314 // (fixes bug introduced by Black on 20050705)
1315
1316 // Note: Cbuf_PreprocessString will be called on this string AGAIN! So we
1317 // have to make sure that no second variable expansion takes place, otherwise
1318 // alias parameters containing dollar signs can have bad effects.
1319 Cmd_QuoteString(buffer2, sizeof(buffer2), buffer, "$", false);
1320 Cbuf_InsertText(cmd, buffer2);
1321}
qbool Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset, qbool putquotes)
quotes a string so that it can be used as a command argument again; quoteset is a string that contain...
Definition cmd.c:1000
static size_t Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmd_alias_t *alias)
Cmd_PreprocessString.
Definition cmd.c:1176
GLuint buffer
Definition glquake.h:630
return ret

References buffer, Cbuf_InsertText(), cmd(), Cmd_PreprocessString(), Cmd_QuoteString(), MAX_INPUTLINE, ret, and cmd_alias_t::value.

Referenced by Cmd_ExecuteString().

◆ Cmd_ExecuteString()

void Cmd_ExecuteString ( cmd_state_t * cmd,
const char * text,
size_t textlen,
cmd_source_t src,
qbool lockmutex )

Parses a single line of text into arguments and tries to execute it.

The text can come from the command buffer, a remote client, or stdin.

Definition at line 2068 of file cmd.c.

2069{
2070 int oldpos;
2071 cmd_function_t *func;
2072 cmd_alias_t *a;
2073
2074 if (lockmutex)
2075 Cbuf_Lock(cmd->cbuf);
2076 oldpos = cmd->cbuf->tokenizebufferpos;
2077 cmd->source = src;
2078
2079 Cmd_TokenizeString (cmd, text);
2080
2081// execute the command line
2082 if (!Cmd_Argc(cmd))
2083 goto done; // no tokens
2084
2085// check functions
2086 for (func = cmd->userdefined->qc_functions; func; func = func->next)
2087 if (!strcasecmp(cmd->argv[0], func->name))
2088 if(cmd->Handle(cmd, func, text, textlen, src))
2089 goto functions_done;
2090
2091 for (func = cmd->engine_functions; func; func=func->next)
2092 if (!strcasecmp (cmd->argv[0], func->name))
2093 if(cmd->Handle(cmd, func, text, textlen, src))
2094 goto functions_done;
2095
2096functions_done:
2097 // If it's a client command and wasn't found and handled, say so.
2098 // Also don't let clients call server aliases.
2099 if (cmd->source == src_client)
2100 {
2101 if (!func)
2102 Con_Printf("Client \"%s\" tried to execute \"%s\"\n", host_client->name, text);
2103 goto done;
2104 }
2105
2106// check alias
2107 // Execute any alias with the same name as a command after the command.
2108 for (a=cmd->userdefined->alias ; a ; a=a->next)
2109 {
2110 if (!strcasecmp (cmd->argv[0], a->name))
2111 {
2113 goto done;
2114 }
2115 }
2116
2117 // If the command was found and handled don't try to handle it as a cvar.
2118 if (func)
2119 goto done;
2120
2121// check cvars
2122 // Xonotic is still maintained so we don't want to hide problems from getting fixed
2123 if (!Cvar_Command(cmd) && (host.framecount > 0 || gamemode == GAME_XONOTIC))
2124 Con_Printf(CON_WARN "Unknown command \"%s\"\n", Cmd_Argv(cmd, 0));
2125done:
2126 cmd->cbuf->tokenizebufferpos = oldpos;
2127 if (lockmutex)
2128 Cbuf_Unlock(cmd->cbuf);
2129}
static void Cmd_TokenizeString(cmd_state_t *cmd, const char *text)
Definition cmd.c:1601
static void Cmd_ExecuteAlias(cmd_state_t *cmd, cmd_alias_t *alias)
Definition cmd.c:1306
@ src_client
came in over a net connection as a clc_stringcmd host_client will be valid during this state.
Definition cmd.h:73
qbool Cvar_Command(cmd_state_t *cmd)
Definition cvar.c:833
prvm_eval_t * src
client_t * host_client
Definition sv_main.c:29
char name[MAX_SCOREBOARDNAME]
Definition server.h:235
unsigned int framecount
incremented every frame, never reset, >0 means Host_AbortCurrentFrame() is possible
Definition host.h:45

References a, Cbuf_Lock(), Cbuf_Unlock(), cmd(), Cmd_Argc(), Cmd_Argv(), Cmd_ExecuteAlias(), Cmd_TokenizeString(), Con_Printf(), CON_WARN, Cvar_Command(), host_static_t::framecount, GAME_XONOTIC, gamemode, host, host_client, client_t::name, cmd_function_t::name, cmd_function_t::next, src, and src_client.

Referenced by CL_ParseServerMessage(), CL_Record_f(), CL_VM_Parse_StuffCmd(), Cmd_PreprocessAndExecuteString(), Key_Message(), SV_ReadClientMessage(), and VM_SV_clientcommand().

◆ Cmd_Exists()

qbool Cmd_Exists ( cmd_state_t * cmd,
const char * cmd_name )

used by the cvar code to check for cvar / command name overlap

Definition at line 1762 of file cmd.c.

1763{
1764 cmd_function_t *func;
1765
1766 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1767 if (!strcmp(cmd_name, func->name))
1768 return true;
1769
1770 for (func=cmd->engine_functions ; func ; func=func->next)
1771 if (!strcmp (cmd_name,func->name))
1772 return true;
1773
1774 return false;
1775}

References cmd(), cmd_function_t::name, and cmd_function_t::next.

Referenced by Cvar_Get(), Cvar_RegisterVariable(), Cvar_RegisterVirtual(), and VM_registercvar().

◆ Cmd_GetCvarValue()

static const char * Cmd_GetCvarValue ( cmd_state_t * cmd,
const char * var,
size_t varlen,
cmd_alias_t * alias )
static

Definition at line 1059 of file cmd.c.

1060{
1061 static char varname[MAX_INPUTLINE]; // cmd_mutex
1062 static char varval[MAX_INPUTLINE]; // cmd_mutex
1063 const char *varstr = NULL;
1064 char *varfunc;
1065 qbool required = false;
1066 qbool optional = false;
1067 static char asis[] = "asis"; // just to suppress const char warnings
1068
1069 if(varlen >= MAX_INPUTLINE)
1070 varlen = MAX_INPUTLINE - 1;
1071 memcpy(varname, var, varlen);
1072 varname[varlen] = 0;
1073 varfunc = strchr(varname, ' ');
1074
1075 if(varfunc)
1076 {
1077 *varfunc = 0;
1078 ++varfunc;
1079 }
1080
1081 if(*var == 0)
1082 {
1083 // empty cvar name?
1084 if(alias)
1085 Con_Printf(CON_WARN "Warning: Could not expand $ in alias %s\n", alias->name);
1086 else
1087 Con_Printf(CON_WARN "Warning: Could not expand $\n");
1088 return "$";
1089 }
1090
1091 if(varfunc)
1092 {
1093 char *p;
1094 // ? means optional
1095 while((p = strchr(varfunc, '?')))
1096 {
1097 optional = true;
1098 memmove(p, p+1, strlen(p)); // with final NUL
1099 }
1100 // ! means required
1101 while((p = strchr(varfunc, '!')))
1102 {
1103 required = true;
1104 memmove(p, p+1, strlen(p)); // with final NUL
1105 }
1106 // kill spaces
1107 while((p = strchr(varfunc, ' ')))
1108 {
1109 memmove(p, p+1, strlen(p)); // with final NUL
1110 }
1111 // if no function is left, NULL it
1112 if(!*varfunc)
1113 varfunc = NULL;
1114 }
1115
1116 if(varname[0] == '$')
1117 varstr = Cmd_GetDirectCvarValue(cmd, Cmd_GetDirectCvarValue(cmd, varname + 1, alias, NULL), alias, NULL);
1118 else
1119 {
1120 qbool is_multiple = false;
1121 // Exception: $* and $n- don't use the quoted form by default
1122 varstr = Cmd_GetDirectCvarValue(cmd, varname, alias, &is_multiple);
1123 if(is_multiple)
1124 if(!varfunc)
1125 varfunc = asis;
1126 }
1127
1128 if(!varstr)
1129 {
1130 if(required)
1131 {
1132 if(alias)
1133 Con_Printf(CON_ERROR "Error: Could not expand $%s in alias %s\n", varname, alias->name);
1134 else
1135 Con_Printf(CON_ERROR "Error: Could not expand $%s\n", varname);
1136 return NULL;
1137 }
1138 else if(optional)
1139 {
1140 return "";
1141 }
1142 else
1143 {
1144 if(alias)
1145 Con_Printf(CON_WARN "Warning: Could not expand $%s in alias %s\n", varname, alias->name);
1146 else
1147 Con_Printf(CON_WARN "Warning: Could not expand $%s\n", varname);
1148 dpsnprintf(varval, sizeof(varval), "$%s", varname);
1149 return varval;
1150 }
1151 }
1152
1153 if(!varfunc || !strcmp(varfunc, "q")) // note: quoted form is default, use "asis" to override!
1154 {
1155 // quote it so it can be used inside double quotes
1156 // we just need to replace " by \", and of course, double backslashes
1157 Cmd_QuoteString(varval, sizeof(varval), varstr, "\"\\", false);
1158 return varval;
1159 }
1160 else if(!strcmp(varfunc, "asis"))
1161 {
1162 return varstr;
1163 }
1164 else
1165 Con_Printf("Unknown variable function %s\n", varfunc);
1166
1167 return varstr;
1168}
static const char * Cmd_GetDirectCvarValue(cmd_state_t *cmd, const char *varname, cmd_alias_t *alias, qbool *is_multiple)
Definition cmd.c:933
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
#define CON_ERROR
Definition console.h:102

References cmd(), Cmd_GetDirectCvarValue(), Cmd_QuoteString(), CON_ERROR, Con_Printf(), CON_WARN, dpsnprintf(), MAX_INPUTLINE, cmd_alias_t::name, NULL, and strlen().

Referenced by Cmd_PreprocessString().

◆ Cmd_GetDirectCvarValue()

static const char * Cmd_GetDirectCvarValue ( cmd_state_t * cmd,
const char * varname,
cmd_alias_t * alias,
qbool * is_multiple )
static

Definition at line 933 of file cmd.c.

934{
935 cvar_t *cvar;
936 long argno;
937 char *endptr;
938 static char vabuf[1024]; // cmd_mutex
939
940 if(is_multiple)
941 *is_multiple = false;
942
943 if(!varname || !*varname)
944 return NULL;
945
946 if(alias)
947 {
948 if(!strcmp(varname, "*"))
949 {
950 if(is_multiple)
951 *is_multiple = true;
952 return Cmd_Args(cmd);
953 }
954 else if(!strcmp(varname, "#"))
955 {
956 return va(vabuf, sizeof(vabuf), "%d", Cmd_Argc(cmd));
957 }
958 else if(varname[strlen(varname) - 1] == '-')
959 {
960 argno = strtol(varname, &endptr, 10);
961 if(endptr == varname + strlen(varname) - 1)
962 {
963 // whole string is a number, apart from the -
964 const char *p = Cmd_Args(cmd);
965 for(; argno > 1; --argno)
967 break;
968 if(p)
969 {
970 if(is_multiple)
971 *is_multiple = true;
972
973 // kill pre-argument whitespace
974 for (;*p && ISWHITESPACE(*p);p++)
975 ;
976
977 return p;
978 }
979 }
980 }
981 else
982 {
983 argno = strtol(varname, &endptr, 10);
984 if(*endptr == 0)
985 {
986 // whole string is a number
987 // NOTE: we already made sure we don't have an empty cvar name!
988 if(argno >= 0 && argno < Cmd_Argc(cmd))
989 return Cmd_Argv(cmd, argno);
990 }
991 }
992 }
993
994 if((cvar = Cvar_FindVar(cmd->cvars, varname, cmd->cvars_flagsmask)) && !(cvar->flags & CF_PRIVATE))
995 return cvar->string;
996
997 return NULL;
998}
#define CF_PRIVATE
cvar should not be $ expanded or sent to the server under any circumstances (rcon_password,...
Definition cmd.h:59
qbool COM_ParseToken_Console(const char **datapointer)
Definition common.c:819

References CF_PRIVATE, cmd(), Cmd_Argc(), Cmd_Args(), Cmd_Argv(), COM_ParseToken_Console(), cvar(), Cvar_FindVar(), ISWHITESPACE, NULL, strlen(), and va().

Referenced by Cmd_GetCvarValue().

◆ Cmd_Init()

void Cmd_Init ( void )

Command execution takes a null terminated string, breaks it into tokens, then searches for a command or variable that matches the first token.

Commands can come from three sources, but the handler functions may choose to dissallow the action or forward it to a remote server if the source is not apropriate.

Definition at line 1492 of file cmd.c.

1493{
1494 cmd_buf_t *cbuf;
1495 unsigned cvars_flagsmask, cmds_flagsmask;
1496
1497 cbuf_mempool = Mem_AllocPool("Command buffer", 0, NULL);
1498 cbuf = (cmd_buf_t *)Mem_Alloc(cbuf_mempool, sizeof(cmd_buf_t));
1499 cbuf->maxsize = CMDBUFSIZE;
1500 cbuf->lock = Thread_CreateMutex();
1501 cbuf->wait = false;
1502 host.cbuf = cbuf;
1503
1504 cbuf->start.prev = cbuf->start.next = &(cbuf->start);
1505 cbuf->deferred.prev = cbuf->deferred.next = &(cbuf->deferred);
1506 cbuf->free.prev = cbuf->free.next = &(cbuf->free);
1507
1508 // FIXME: Get rid of cmd_iter_all eventually. This is just a hack to reduce the amount of work to make the interpreters dynamic.
1510
1511 // local console
1512 if (cls.state == ca_dedicated)
1513 {
1514 cvars_flagsmask = CF_SERVER;
1515 cmds_flagsmask = CF_SERVER | CF_SERVER_FROM_CLIENT;
1516 }
1517 else
1518 {
1519 cvars_flagsmask = CF_CLIENT | CF_SERVER;
1521 }
1522 cmd_iter_all[0].cmd = cmd_local = Cmd_AddInterpreter(cbuf, &cvars_all, cvars_flagsmask, cmds_flagsmask, &cmd_userdefined_all);
1524
1525 // server commands received from clients have no reason to access cvars, cvar expansion seems perilous.
1528
1529 cmd_iter_all[2].cmd = NULL;
1530//
1531// register our commands
1532//
1533 // client-only commands
1534 Cmd_AddCommand(CF_SHARED, "wait", Cmd_Wait_f, "make script execution wait for next rendered frame");
1535
1536 // maintenance commands used for upkeep of cvars and saved configs
1537 Cmd_AddCommand(CF_SHARED, "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in quake.rc script)");
1538 Cmd_AddCommand(CF_SHARED, "cvar_lockdefaults", Cvar_LockDefaults_f, "stores the current values of all cvars into their default values, only used once during startup after parsing default.cfg");
1539 Cmd_AddCommand(CF_SHARED, "cvar_resettodefaults_all", Cvar_ResetToDefaults_All_f, "sets all cvars to their locked default values");
1540 Cmd_AddCommand(CF_SHARED, "cvar_resettodefaults_nosaveonly", Cvar_ResetToDefaults_NoSaveOnly_f, "sets all non-saved cvars to their locked default values (variables that will not be saved to config.cfg)");
1541 Cmd_AddCommand(CF_SHARED, "cvar_resettodefaults_saveonly", Cvar_ResetToDefaults_SaveOnly_f, "sets all saved cvars to their locked default values (variables that will be saved to config.cfg)");
1542
1543 // general console commands used in multiple environments
1544 Cmd_AddCommand(CF_SHARED, "exec", Cmd_Exec_f, "execute a script file");
1545 Cmd_AddCommand(CF_SHARED, "echo",Cmd_Echo_f, "print a message to the console (useful in scripts)");
1546 Cmd_AddCommand(CF_SHARED, "alias",Cmd_Alias_f, "create a script function (parameters are passed in as $X (being X a number), $* for all parameters, $X- for all parameters starting from $X). Without arguments show the list of all alias");
1547 Cmd_AddCommand(CF_SHARED, "unalias",Cmd_UnAlias_f, "remove an alias");
1548 Cmd_AddCommand(CF_SHARED, "set", Cvar_Set_f, "create or change the value of a console variable");
1549 Cmd_AddCommand(CF_SHARED, "seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg");
1550 Cmd_AddCommand(CF_SHARED, "unset", Cvar_Del_f, "delete a cvar (does not work for static ones like _cl_name, or read-only ones)");
1551
1552#ifdef FILLALLCVARSWITHRUBBISH
1553 Cmd_AddCommand(CF_SHARED, "fillallcvarswithrubbish", Cvar_FillAll_f, "fill all cvars with a specified number of characters to provoke buffer overruns");
1554#endif /* FILLALLCVARSWITHRUBBISH */
1555
1556 // 2000-01-09 CmdList, CvarList commands By Matthias "Maddes" Buecher
1557 // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
1558 Cmd_AddCommand(CF_SHARED, "cmdlist", Cmd_List_f, "lists all console commands beginning with the specified prefix or matching the specified wildcard pattern");
1559 Cmd_AddCommand(CF_SHARED, "cvarlist", Cvar_List_f, "lists all console variables beginning with the specified prefix or matching the specified wildcard pattern");
1560 Cmd_AddCommand(CF_SHARED, "apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description");
1561 Cmd_AddCommand(CF_SHARED, "find", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description");
1562
1563 Cmd_AddCommand(CF_SHARED, "defer", Cmd_Defer_f, "execute a command in the future");
1564
1565 // DRESK - 5/14/06
1566 // Support Doom3-style Toggle Command
1567 Cmd_AddCommand(CF_SHARED | CF_CLIENT_FROM_SERVER, "toggle", Cmd_Toggle_f, "toggles a console variable's values (use for more info)");
1568}
static void Cmd_Wait_f(cmd_state_t *cmd)
Definition cmd.c:65
static void Cmd_Apropos_f(cmd_state_t *cmd)
Definition cmd.c:1400
static void Cmd_Defer_f(cmd_state_t *cmd)
Definition cmd.c:79
static void Cmd_List_f(cmd_state_t *cmd)
Definition cmd.c:1352
qbool Cmd_SV_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src)
Definition cmd.c:2045
static void Cmd_StuffCmds_f(cmd_state_t *cmd)
Definition cmd.c:463
cmd_userdefined_t cmd_userdefined_all
aliases and csqc functions
Definition cmd.c:28
static void Cmd_Echo_f(cmd_state_t *cmd)
Definition cmd.c:717
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
Definition cmd.c:1661
static cmd_state_t * Cmd_AddInterpreter(cmd_buf_t *cbuf, cvar_state_t *cvars, unsigned cvars_flagsmask, unsigned cmds_flagsmask, cmd_userdefined_t *userdefined)
Definition cmd.c:1470
static void Cmd_UnAlias_f(cmd_state_t *cmd)
Definition cmd.c:889
qbool Cmd_CL_Callback(cmd_state_t *cmd, cmd_function_t *func, const char *text, size_t textlen, cmd_source_t src)
Definition cmd.c:2017
static void Cmd_Toggle_f(cmd_state_t *cmd)
Definition cmd.c:735
cmd_state_t * cmd_serverfromclient
command interpreter for server commands received over network from clients uses cmddefs_null
Definition cmd.c:26
static void Cmd_Exec_f(cmd_state_t *cmd)
Definition cmd.c:685
static void Cmd_Alias_f(cmd_state_t *cmd)
Definition cmd.c:813
cmd_userdefined_t cmd_userdefined_null
intentionally empty
Definition cmd.c:29
#define CF_SHARED
Definition cmd.h:67
#define CF_USERINFO
command or cvar used to communicate userinfo to the server
Definition cmd.h:57
#define CF_CLIENT_FROM_SERVER
command that the server is allowed to execute on the client
Definition cmd.h:50
void Cvar_Del_f(cmd_state_t *cmd)
Definition cvar.c:1110
void Cvar_ResetToDefaults_NoSaveOnly_f(cmd_state_t *cmd)
Definition cvar.c:952
void Cvar_ResetToDefaults_All_f(cmd_state_t *cmd)
Definition cvar.c:940
void Cvar_Set_f(cmd_state_t *cmd)
Definition cvar.c:1060
void Cvar_LockDefaults_f(cmd_state_t *cmd)
Definition cvar.c:871
cvar_state_t cvars_all
Definition cvar.c:28
cvar_state_t cvars_null
Definition cvar.c:29
void Cvar_SetA_f(cmd_state_t *cmd)
Definition cvar.c:1085
void Cvar_List_f(cmd_state_t *cmd)
Definition cvar.c:1008
void Cvar_ResetToDefaults_SaveOnly_f(cmd_state_t *cmd)
Definition cvar.c:965
#define CMDBUFSIZE
maximum script size that can be loaded by the exec command (8192 in Quake)
Definition qdefs.h:100
qbool(* Handle)(struct cmd_state_s *, struct cmd_function_s *, const char *, size_t, enum cmd_source_s)
Definition cmd.h:147
cmd_buf_t * cbuf
Definition host.h:51
#define Thread_CreateMutex()
Definition thread.h:15

References ca_dedicated, host_static_t::cbuf, cbuf_mempool, CF_CLIENT, CF_CLIENT_FROM_SERVER, CF_SERVER, CF_SERVER_FROM_CLIENT, CF_SHARED, CF_USERINFO, cls, cmd_iter_t::cmd, Cmd_AddCommand(), Cmd_AddInterpreter(), Cmd_Alias_f(), Cmd_Apropos_f(), Cmd_CL_Callback(), Cmd_Defer_f(), Cmd_Echo_f(), Cmd_Exec_f(), cmd_iter_all, Cmd_List_f(), cmd_local, cmd_serverfromclient, Cmd_StuffCmds_f(), Cmd_SV_Callback(), Cmd_Toggle_f(), Cmd_UnAlias_f(), cmd_userdefined_all, cmd_userdefined_null, Cmd_Wait_f(), CMDBUFSIZE, Cvar_Del_f(), Cvar_List_f(), Cvar_LockDefaults_f(), Cvar_ResetToDefaults_All_f(), Cvar_ResetToDefaults_NoSaveOnly_f(), Cvar_ResetToDefaults_SaveOnly_f(), Cvar_Set_f(), Cvar_SetA_f(), cvars_all, cvars_null, cmd_buf_t::deferred, cmd_buf_t::free, cmd_state_t::Handle, host, cmd_buf_t::lock, cmd_buf_t::maxsize, Mem_Alloc, Mem_AllocPool, llist_t::next, NULL, llist_t::prev, cmd_buf_t::start, client_static_t::state, tempmempool, Thread_CreateMutex, and cmd_buf_t::wait.

Referenced by Host_Init().

◆ Cmd_List_f()

static void Cmd_List_f ( cmd_state_t * cmd)
static

Definition at line 1352 of file cmd.c.

1353{
1354 cmd_function_t *func;
1355 const char *partial;
1356 size_t len;
1357 int count;
1358 qbool ispattern;
1359
1360 if (Cmd_Argc(cmd) > 1)
1361 {
1362 partial = Cmd_Argv(cmd, 1);
1363 len = strlen(partial);
1364 ispattern = (strchr(partial, '*') || strchr(partial, '?'));
1365 }
1366 else
1367 {
1368 partial = NULL;
1369 len = 0;
1370 ispattern = false;
1371 }
1372
1373 count = 0;
1374 for (func = cmd->userdefined->qc_functions; func; func = func->next)
1375 {
1376 if (partial && (ispattern ? !matchpattern_with_separator(func->name, partial, false, "", false) : strncmp(partial, func->name, len)))
1377 continue;
1378 Con_Printf("%s : %s\n", func->name, func->description);
1379 count++;
1380 }
1381 for (func = cmd->engine_functions; func; func = func->next)
1382 {
1383 if (partial && (ispattern ? !matchpattern_with_separator(func->name, partial, false, "", false) : strncmp(partial, func->name, len)))
1384 continue;
1385 Con_Printf("%s : %s\n", func->name, func->description);
1386 count++;
1387 }
1388
1389 if (len)
1390 {
1391 if(ispattern)
1392 Con_Printf("%i Command%s matching \"%s\"\n\n", count, (count > 1) ? "s" : "", partial);
1393 else
1394 Con_Printf("%i Command%s beginning with \"%s\"\n\n", count, (count > 1) ? "s" : "", partial);
1395 }
1396 else
1397 Con_Printf("%i Command%s\n\n", count, (count > 1) ? "s" : "");
1398}

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), count, cmd_function_t::description, matchpattern_with_separator(), cmd_function_t::name, cmd_function_t::next, NULL, and strlen().

Referenced by Cmd_Init().

◆ Cmd_NoOperation_f()

void Cmd_NoOperation_f ( cmd_state_t * cmd)

Definition at line 2240 of file cmd.c.

2241{
2242}

Referenced by S_Init().

◆ Cmd_PreprocessAndExecuteString()

void Cmd_PreprocessAndExecuteString ( cmd_state_t * cmd,
const char * text,
size_t textlen,
cmd_source_t src,
qbool lockmutex )

Like Cmd_ExecuteString, but with variable expansion.

Definition at line 1323 of file cmd.c.

1324{
1325 char preprocessed[MAX_INPUTLINE];
1326 size_t preprocessed_len;
1327 const char *firstchar;
1328
1329 firstchar = text;
1330 while(*firstchar && ISWHITESPACE(*firstchar))
1331 ++firstchar;
1332 if((strncmp(firstchar, "alias", 5) || !ISWHITESPACE(firstchar[5]))
1333 && (strncmp(firstchar, "bind", 4) || !ISWHITESPACE(firstchar[4]))
1334 && (strncmp(firstchar, "in_bind", 7) || !ISWHITESPACE(firstchar[7])))
1335 {
1336 if((preprocessed_len = Cmd_PreprocessString(cmd, text, preprocessed, sizeof(preprocessed), NULL)))
1337 Cmd_ExecuteString(cmd, preprocessed, preprocessed_len, src, lockmutex);
1338 }
1339 else
1340 Cmd_ExecuteString(cmd, text, textlen, src, lockmutex);
1341}
void Cmd_ExecuteString(cmd_state_t *cmd, const char *text, size_t textlen, cmd_source_t src, qbool lockmutex)
Parses a single line of text into arguments and tries to execute it.
Definition cmd.c:2068

References cmd(), Cmd_ExecuteString(), Cmd_PreprocessString(), ISWHITESPACE, MAX_INPUTLINE, NULL, and src.

Referenced by Cbuf_Execute(), and RCon_Execute().

◆ Cmd_PreprocessString()

static size_t Cmd_PreprocessString ( cmd_state_t * cmd,
const char * intext,
char * outtext,
unsigned maxoutlen,
cmd_alias_t * alias )
static

Cmd_PreprocessString.

Preprocesses strings and replaces $*, $param#, $cvar accordingly. Also strips comments. Returns the number of bytes written to *outtext excluding the \0 terminator.

Definition at line 1176 of file cmd.c.

1177{
1178 const char *in;
1179 size_t eat, varlen;
1180 unsigned outlen;
1181 const char *val;
1182
1183 // don't crash if there's no room in the outtext buffer
1184 if( maxoutlen == 0 ) {
1185 return 0;
1186 }
1187 maxoutlen--; // because of \0
1188
1189 in = intext;
1190 outlen = 0;
1191
1192 while( *in && outlen < maxoutlen ) {
1193 if( *in == '$' ) {
1194 // this is some kind of expansion, see what comes after the $
1195 in++;
1196
1197 // The console does the following preprocessing:
1198 //
1199 // - $$ is transformed to a single dollar sign.
1200 // - $var or ${var} are expanded to the contents of the named cvar,
1201 // with quotation marks and backslashes quoted so it can safely
1202 // be used inside quotation marks (and it should always be used
1203 // that way)
1204 // - ${var asis} inserts the cvar value as is, without doing this
1205 // quoting
1206 // - ${var ?} silently expands to the empty string if
1207 // $var does not exist
1208 // - ${var !} fails expansion and executes nothing if
1209 // $var does not exist
1210 // - prefix the cvar name with a dollar sign to do indirection;
1211 // for example, if $x has the value timelimit, ${$x} will return
1212 // the value of $timelimit
1213 // - when expanding an alias, the special variable name $* refers
1214 // to all alias parameters, and a number refers to that numbered
1215 // alias parameter, where the name of the alias is $0, the first
1216 // parameter is $1 and so on; as a special case, $* inserts all
1217 // parameters, without extra quoting, so one can use $* to just
1218 // pass all parameters around. All parameters starting from $n
1219 // can be referred to as $n- (so $* is equivalent to $1-).
1220 // - ${* q} and ${n- q} force quoting anyway
1221 //
1222 // Note: when expanding an alias, cvar expansion is done in the SAME step
1223 // as alias expansion so that alias parameters or cvar values containing
1224 // dollar signs have no unwanted bad side effects. However, this needs to
1225 // be accounted for when writing complex aliases. For example,
1226 // alias foo "set x NEW; echo $x"
1227 // actually expands to
1228 // "set x NEW; echo OLD"
1229 // and will print OLD! To work around this, use a second alias:
1230 // alias foo "set x NEW; foo2"
1231 // alias foo2 "echo $x"
1232 //
1233 // Also note: lines starting with alias are exempt from cvar expansion.
1234 // If you want cvar expansion, write "alias" instead:
1235 //
1236 // set x 1
1237 // alias foo "echo $x"
1238 // "alias" bar "echo $x"
1239 // set x 2
1240 //
1241 // foo will print 2, because the variable $x will be expanded when the alias
1242 // gets expanded. bar will print 1, because the variable $x was expanded
1243 // at definition time. foo can be equivalently defined as
1244 //
1245 // "alias" foo "echo $$x"
1246 //
1247 // because at definition time, $$ will get replaced to a single $.
1248
1249 if( *in == '$' ) {
1250 val = "$";
1251 eat = 1;
1252 } else if(*in == '{') {
1253 varlen = strcspn(in + 1, "}");
1254 if(in[varlen + 1] == '}')
1255 {
1256 val = Cmd_GetCvarValue(cmd, in + 1, varlen, alias);
1257 if(!val)
1258 return 0;
1259 eat = varlen + 2;
1260 }
1261 else
1262 {
1263 // ran out of data?
1264 val = NULL;
1265 eat = varlen + 1;
1266 }
1267 } else {
1268 varlen = strspn(in, "#*0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-");
1269 val = Cmd_GetCvarValue(cmd, in, varlen, alias);
1270 if(!val)
1271 return 0;
1272 eat = varlen;
1273 }
1274 if(val)
1275 {
1276 // insert the cvar value
1277 while(*val && outlen < maxoutlen)
1278 outtext[outlen++] = *val++;
1279 in += eat;
1280 }
1281 else
1282 {
1283 // copy the unexpanded text
1284 outtext[outlen++] = '$';
1285 while(eat && outlen < maxoutlen)
1286 {
1287 outtext[outlen++] = *in++;
1288 --eat;
1289 }
1290 }
1291 }
1292 else
1293 outtext[outlen++] = *in++;
1294 }
1295 outtext[outlen] = '\0';
1296 return outlen;
1297}
static const char * Cmd_GetCvarValue(cmd_state_t *cmd, const char *var, size_t varlen, cmd_alias_t *alias)
Definition cmd.c:1059

References cmd(), Cmd_GetCvarValue(), and NULL.

Referenced by Cmd_ExecuteAlias(), and Cmd_PreprocessAndExecuteString().

◆ Cmd_QuoteString()

qbool Cmd_QuoteString ( char * out,
size_t outlen,
const char * in,
const char * quoteset,
qbool putquotes )

quotes a string so that it can be used as a command argument again; quoteset is a string that contains one or more of ", \, $ and specifies the characters to be quoted (you usually want to either pass ""\" or ""\$").

Returns true on success, and false on overrun (in which case out will contain a part of the quoted string). If putquotes is set, the enclosing quote marks are also put.

Definition at line 1000 of file cmd.c.

1001{
1002 qbool quote_quot = !!strchr(quoteset, '"');
1003 qbool quote_backslash = !!strchr(quoteset, '\\');
1004 qbool quote_dollar = !!strchr(quoteset, '$');
1005
1006 if(putquotes)
1007 {
1008 if(outlen <= 2)
1009 {
1010 *out++ = 0;
1011 return false;
1012 }
1013 *out++ = '"'; --outlen;
1014 --outlen;
1015 }
1016
1017 while(*in)
1018 {
1019 if(*in == '"' && quote_quot)
1020 {
1021 if(outlen <= 2)
1022 goto fail;
1023 *out++ = '\\'; --outlen;
1024 *out++ = '"'; --outlen;
1025 }
1026 else if(*in == '\\' && quote_backslash)
1027 {
1028 if(outlen <= 2)
1029 goto fail;
1030 *out++ = '\\'; --outlen;
1031 *out++ = '\\'; --outlen;
1032 }
1033 else if(*in == '$' && quote_dollar)
1034 {
1035 if(outlen <= 2)
1036 goto fail;
1037 *out++ = '$'; --outlen;
1038 *out++ = '$'; --outlen;
1039 }
1040 else
1041 {
1042 if(outlen <= 1)
1043 goto fail;
1044 *out++ = *in; --outlen;
1045 }
1046 ++in;
1047 }
1048 if(putquotes)
1049 *out++ = '"';
1050 *out++ = 0;
1051 return true;
1052fail:
1053 if(putquotes)
1054 *out++ = '"';
1055 *out++ = 0;
1056 return false;
1057}

Referenced by Cmd_ExecuteAlias(), Cmd_GetCvarValue(), Cvar_WriteVariables(), Key_PrintBindList(), and Key_WriteBindings().

◆ Cmd_RestoreInitState()

void Cmd_RestoreInitState ( void )

Restores cvars, commands and aliases to their init values and deletes any that were added since init.

Definition at line 2180 of file cmd.c.

2181{
2182 cmd_iter_t *cmd_iter;
2183 for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
2184 {
2185 cmd_state_t *cmd = cmd_iter->cmd;
2186 cmd_function_t *f, **fp;
2187 cmd_alias_t *a, **ap;
2188 for (fp = &cmd->userdefined->qc_functions; (f = *fp);)
2189 {
2190 if (f->initstate)
2191 fp = &f->next;
2192 else
2193 {
2194 // destroy this command, it didn't exist at init
2195 Con_DPrintf("Cmd_RestoreInitState: Destroying command %s\n", f->name);
2196 *fp = f->next;
2197 Z_Free(f);
2198 }
2199 }
2200 for (fp = &cmd->engine_functions; (f = *fp);)
2201 {
2202 if (f->initstate)
2203 fp = &f->next;
2204 else
2205 {
2206 // destroy this command, it didn't exist at init
2207 Con_DPrintf("Cmd_RestoreInitState: Destroying command %s\n", f->name);
2208 *fp = f->next;
2209 Z_Free(f);
2210 }
2211 }
2212 for (ap = &cmd->userdefined->alias; (a = *ap);)
2213 {
2214 if (a->initstate)
2215 {
2216 // restore this alias, it existed at init
2217 if (strcmp(a->value ? a->value : "", a->initialvalue ? a->initialvalue : ""))
2218 {
2219 Con_DPrintf("Cmd_RestoreInitState: Restoring alias %s\n", a->name);
2220 if (a->value)
2221 Z_Free(a->value);
2222 a->value = Mem_strdup(zonemempool, a->initialvalue);
2223 }
2224 ap = &a->next;
2225 }
2226 else
2227 {
2228 // free this alias, it didn't exist at init...
2229 Con_DPrintf("Cmd_RestoreInitState: Destroying alias %s\n", a->name);
2230 *ap = a->next;
2231 if (a->value)
2232 Z_Free(a->value);
2233 Z_Free(a);
2234 }
2235 }
2236 }
2238}
void Cvar_RestoreInitState(cvar_state_t *cvars)
Definition cvar.c:901
mempool_t * zonemempool
Definition zone.c:796
#define Mem_strdup(pool, s)
Definition zone.h:97

References a, cmd(), cmd_iter_t::cmd, cmd_iter_all, Con_DPrintf(), Cvar_RestoreInitState(), cvars_all, f, Mem_strdup, cmd_alias_t::next, Z_Free, and zonemempool.

Referenced by Host_LoadConfig_f().

◆ Cmd_SaveInitState()

void Cmd_SaveInitState ( void )

called by Host_Init, this marks cvars, commands and aliases with their init values

Definition at line 2159 of file cmd.c.

2160{
2161 cmd_iter_t *cmd_iter;
2162 for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
2163 {
2164 cmd_state_t *cmd = cmd_iter->cmd;
2166 cmd_alias_t *a;
2167 for (f = cmd->userdefined->qc_functions; f; f = f->next)
2168 f->initstate = true;
2169 for (f = cmd->engine_functions; f; f = f->next)
2170 f->initstate = true;
2171 for (a = cmd->userdefined->alias; a; a = a->next)
2172 {
2173 a->initstate = true;
2174 a->initialvalue = Mem_strdup(zonemempool, a->value);
2175 }
2176 }
2178}
void Cvar_SaveInitState(cvar_state_t *cvars)
Definition cvar.c:892

References a, cmd(), cmd_iter_t::cmd, cmd_iter_all, Cvar_SaveInitState(), cvars_all, f, Mem_strdup, and zonemempool.

Referenced by Host_Init().

◆ Cmd_Shutdown()

void Cmd_Shutdown ( void )

Definition at line 1575 of file cmd.c.

1576{
1577 cmd_iter_t *cmd_iter;
1578 for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
1579 {
1580 cmd_state_t *cmd = cmd_iter->cmd;
1581
1582 if (cmd->cbuf->lock)
1583 {
1584 // we usually have this locked when we get here from Host_Quit_f
1585 Cbuf_Unlock(cmd->cbuf);
1586 }
1587
1588 Mem_FreePool(&cmd->mempool);
1589 }
1590}
#define Mem_FreePool(pool)
Definition zone.h:105

References Cbuf_Unlock(), cmd(), cmd_iter_t::cmd, cmd_iter_all, and Mem_FreePool.

Referenced by Host_Shutdown().

◆ Cmd_StuffCmds_f()

static void Cmd_StuffCmds_f ( cmd_state_t * cmd)
static

Definition at line 463 of file cmd.c.

464{
465 int i, j, l;
466 // this is for all commandline options combined (and is bounds checked)
467 char build[MAX_INPUTLINE];
468
469 if (Cmd_Argc (cmd) != 1)
470 {
471 Con_Print("stuffcmds : execute command line parameters\n");
472 return;
473 }
474
475 // no reason to run the commandline arguments twice
477 return;
478
479 host_stuffcmdsrun = true;
480 build[0] = 0;
481 l = 0;
482 for (i = 0;i < sys.argc;i++)
483 {
484 if (sys.argv[i] && sys.argv[i][0] == '+' && (sys.argv[i][1] < '0' || sys.argv[i][1] > '9') && l + strlen(sys.argv[i]) - 1 <= sizeof(build) - 1)
485 {
486 j = 1;
487 while (sys.argv[i][j])
488 build[l++] = sys.argv[i][j++];
489 i++;
490 for (;i < sys.argc;i++)
491 {
492 if (!sys.argv[i])
493 continue;
494 if ((sys.argv[i][0] == '+' || sys.argv[i][0] == '-') && (sys.argv[i][1] < '0' || sys.argv[i][1] > '9'))
495 break;
496 if (l + strlen(sys.argv[i]) + 4 > sizeof(build) - 1)
497 break;
498 build[l++] = ' ';
499 if (strchr(sys.argv[i], ' '))
500 build[l++] = '\"';
501 for (j = 0;sys.argv[i][j];j++)
502 build[l++] = sys.argv[i][j];
503 if (strchr(sys.argv[i], ' '))
504 build[l++] = '\"';
505 }
506 build[l++] = '\n';
507 i--;
508 }
509 }
510 // now terminate the combined string and prepend it to the command buffer
511 // we already reserved space for the terminator
512 build[l++] = 0;
513 Cbuf_InsertText (cmd, build);
514}
qbool host_stuffcmdsrun
Definition cmd.c:41
int argc
Definition sys.h:146
const char ** argv
Definition sys.h:147
sys_t sys
Definition sys_shared.c:42

References sys_t::argc, sys_t::argv, Cbuf_InsertText(), cmd(), Cmd_Argc(), Con_Print(), host_stuffcmdsrun, i, MAX_INPUTLINE, strlen(), and sys.

Referenced by Cmd_Init().

◆ Cmd_SV_Callback()

qbool Cmd_SV_Callback ( cmd_state_t * cmd,
cmd_function_t * func,
const char * text,
size_t textlen,
cmd_source_t src )

Definition at line 2045 of file cmd.c.

2046{
2047 if(func->qcfunc && (func->flags & CF_SERVER))
2048 return SV_VM_ConsoleCommand(text, textlen);
2049 else if (src == src_client)
2050 {
2051 if((func->flags & CF_CHEAT) && !sv_cheats.integer)
2052 SV_ClientPrintf(CON_WARN "No cheats allowed. The server must have sv_cheats set to 1\n");
2053 else
2054 func->function(cmd);
2055 return true;
2056 }
2057 return false;
2058}
cvar_t sv_cheats
Definition sv_ccmds.c:28
#define CF_CHEAT
command or cvar that gives an unfair advantage over other players and is blocked unless sv_cheats is ...
Definition cmd.h:52
void SV_ClientPrintf(const char *fmt,...) DP_FUNC_PRINTF(1)
Definition sv_send.c:72

References CF_CHEAT, CF_SERVER, cmd(), CON_WARN, cmd_function_t::flags, cmd_function_t::function, cvar_t::integer, cmd_function_t::qcfunc, src, src_client, sv_cheats, SV_ClientPrintf(), and SV_VM_ConsoleCommand().

Referenced by Cmd_Init().

◆ Cmd_Toggle_f()

static void Cmd_Toggle_f ( cmd_state_t * cmd)
static

Definition at line 735 of file cmd.c.

736{
737 // Acquire Number of Arguments
738 int nNumArgs = Cmd_Argc(cmd);
739
740 if(nNumArgs == 1)
741 // No Arguments Specified; Print Usage
742 Con_Print("Toggle Console Variable - Usage\n toggle <variable> - toggles between 0 and 1\n toggle <variable> <value> - toggles between 0 and <value>\n toggle <variable> [string 1] [string 2]...[string n] - cycles through all strings\n");
743 else
744 { // Correct Arguments Specified
745 // Acquire Potential CVar
746 cvar_t* cvCVar = Cvar_FindVar(cmd->cvars, Cmd_Argv(cmd, 1), cmd->cvars_flagsmask);
747
748 if(cvCVar != NULL)
749 { // Valid CVar
750 if(nNumArgs == 2)
751 { // Default Usage
752 if(cvCVar->integer)
753 Cvar_SetValueQuick(cvCVar, 0);
754 else
755 Cvar_SetValueQuick(cvCVar, 1);
756 }
757 else
758 if(nNumArgs == 3)
759 { // 0 and Specified Usage
760 if(cvCVar->integer == atoi(Cmd_Argv(cmd, 2) ) )
761 // CVar is Specified Value; // Reset to 0
762 Cvar_SetValueQuick(cvCVar, 0);
763 else
764 if(cvCVar->integer == 0)
765 // CVar is 0; Specify Value
766 Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, 2) );
767 else
768 // CVar does not match; Reset to 0
769 Cvar_SetValueQuick(cvCVar, 0);
770 }
771 else
772 { // Variable Values Specified
773 int nCnt;
774 int bFound = 0;
775
776 for(nCnt = 2; nCnt < nNumArgs; nCnt++)
777 { // Cycle through Values
778 if( strcmp(cvCVar->string, Cmd_Argv(cmd, nCnt) ) == 0)
779 { // Current Value Located; Increment to Next
780 if( (nCnt + 1) == nNumArgs)
781 // Max Value Reached; Reset
782 Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, 2) );
783 else
784 // Next Value
785 Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, nCnt + 1) );
786
787 // End Loop
788 nCnt = nNumArgs;
789 // Assign Found
790 bFound = 1;
791 }
792 }
793 if(!bFound)
794 // Value not Found; Reset to Original
795 Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, 2) );
796 }
797
798 }
799 else
800 { // Invalid CVar
801 Con_Printf(CON_WARN "ERROR : CVar '%s' not found\n", Cmd_Argv(cmd, 1) );
802 }
803 }
804}
void Cvar_SetValueQuick(cvar_t *var, float value)
Definition cvar.c:473
void Cvar_SetQuick(cvar_t *var, const char *value)
Definition cvar.c:436
const char * string
Definition cvar.h:71

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), CON_WARN, Cvar_FindVar(), Cvar_SetQuick(), Cvar_SetValueQuick(), cvar_t::integer, NULL, and cvar_t::string.

Referenced by Cmd_Init().

◆ Cmd_TokenizeString()

static void Cmd_TokenizeString ( cmd_state_t * cmd,
const char * text )
static

Definition at line 1601 of file cmd.c.

1602{
1603 int l;
1604
1605 cmd->argc = 0;
1606 cmd->args = NULL;
1607 cmd->cmdline = NULL;
1608
1609 while (1)
1610 {
1611 // skip whitespace up to a /n
1612 while (*text && ISWHITESPACE(*text) && *text != '\r' && *text != '\n')
1613 text++;
1614
1615 // line endings:
1616 // UNIX: \n
1617 // Mac: \r
1618 // Windows: \r\n
1619 if (*text == '\n' || *text == '\r')
1620 {
1621 // a newline separates commands in the buffer
1622 if (*text == '\r' && text[1] == '\n')
1623 text++;
1624 text++;
1625 break;
1626 }
1627
1628 if (!*text)
1629 return;
1630
1631 if(!cmd->argc)
1632 cmd->cmdline = text;
1633 if (cmd->argc == 1)
1634 cmd->args = text;
1635
1636 if (!COM_ParseToken_Console(&text))
1637 return;
1638
1639 if (cmd->argc < MAX_ARGS)
1640 {
1641 l = (int)strlen(com_token) + 1;
1642 if (cmd->cbuf->tokenizebufferpos + l > CMD_TOKENIZELENGTH)
1643 {
1644 Con_Printf(CON_WARN "Cmd_TokenizeString: ran out of %i character buffer space for command arguments\n", CMD_TOKENIZELENGTH);
1645 break;
1646 }
1647 memcpy (cmd->cbuf->tokenizebuffer + cmd->cbuf->tokenizebufferpos, com_token, l);
1648 cmd->argv[cmd->argc] = cmd->cbuf->tokenizebuffer + cmd->cbuf->tokenizebufferpos;
1649 cmd->cbuf->tokenizebufferpos += l;
1650 cmd->argc++;
1651 }
1652 }
1653}
char com_token[MAX_INPUTLINE]
Definition common.c:39
static int(ZEXPORT *qz_inflate)(z_stream *strm
#define MAX_ARGS
maximum number of parameters to a console command or alias
Definition qdefs.h:101
#define CMD_TOKENIZELENGTH
maximum tokenizable commandline length (counting trailing 0)
Definition qdefs.h:166

References cmd(), CMD_TOKENIZELENGTH, COM_ParseToken_Console(), com_token, Con_Printf(), CON_WARN, int(), ISWHITESPACE, MAX_ARGS, NULL, and strlen().

Referenced by Cmd_ExecuteString().

◆ Cmd_UnAlias_f()

static void Cmd_UnAlias_f ( cmd_state_t * cmd)
static

Definition at line 889 of file cmd.c.

890{
891 cmd_alias_t *a, *p;
892 int i;
893 const char *s;
894
895 if(Cmd_Argc(cmd) == 1)
896 {
897 Con_Print("unalias: Usage: unalias alias1 [alias2 ...]\n");
898 return;
899 }
900
901 for(i = 1; i < Cmd_Argc(cmd); ++i)
902 {
903 s = Cmd_Argv(cmd, i);
904 p = NULL;
905 for(a = cmd->userdefined->alias; a; p = a, a = a->next)
906 {
907 if(!strcmp(s, a->name))
908 {
909 if (a->initstate) // we can not remove init aliases
910 continue;
911 if(a == cmd->userdefined->alias)
912 cmd->userdefined->alias = a->next;
913 if(p)
914 p->next = a->next;
915 Z_Free(a->value);
916 Z_Free(a);
917 break;
918 }
919 }
920 if(!a)
921 Con_Printf("unalias: %s alias not found\n", s);
922 }
923}

References a, cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), i, cmd_alias_t::next, NULL, and Z_Free.

Referenced by Cmd_Init().

◆ Cmd_Wait_f()

static void Cmd_Wait_f ( cmd_state_t * cmd)
static

Definition at line 65 of file cmd.c.

66{
67 cmd->cbuf->wait = true;
68}

References cmd().

Referenced by Cmd_Init().

Variable Documentation

◆ cbuf_mempool

mempool_t* cbuf_mempool

Definition at line 38 of file cmd.c.

Referenced by Cbuf_LinkString(), Cbuf_NodeGet(), and Cmd_Init().

◆ cmd_iter_all

cmd_iter_t* cmd_iter_all
static

Definition at line 36 of file cmd.c.

Referenced by Cmd_AddCommand(), Cmd_Init(), Cmd_RestoreInitState(), Cmd_SaveInitState(), and Cmd_Shutdown().

◆ cmd_local

◆ cmd_serverfromclient

cmd_state_t* cmd_serverfromclient

command interpreter for server commands received over network from clients uses cmddefs_null

Definition at line 26 of file cmd.c.

Referenced by Cmd_Init(), SV_ReadClientMessage(), and VM_SV_clientcommand().

◆ cmd_userdefined_all

cmd_userdefined_t cmd_userdefined_all

aliases and csqc functions

Definition at line 28 of file cmd.c.

Referenced by Cmd_Init().

◆ cmd_userdefined_null

cmd_userdefined_t cmd_userdefined_null

intentionally empty

Definition at line 29 of file cmd.c.

Referenced by Cmd_Init().

◆ host_stuffcmdsrun

qbool host_stuffcmdsrun = false

Definition at line 41 of file cmd.c.

Referenced by Cmd_StuffCmds_f().

◆ prvm_runawaycheck

qbool prvm_runawaycheck
extern

Definition at line 60 of file prvm_edict.c.

Referenced by Cbuf_Execute(), and while().

◆ sv_cheats

cvar_t sv_cheats
extern

Definition at line 28 of file sv_ccmds.c.

28{CF_SERVER | CF_NOTIFY, "sv_cheats", "0", "enables cheat commands in any game, and cheat impulses in dpmod"};
#define CF_NOTIFY
cvar should trigger a chat notification to all connected clients when changed
Definition cmd.h:55

Referenced by Cmd_SV_Callback(), and SV_InitOperatorCommands().