=============================================================================
*/
-static sizebuf_t cmd_text;
-
-/*
-============
-Cbuf_Init
-============
-*/
-void Cbuf_Init (void)
-{
// LordHavoc: inreased this from 8192 to 32768
- SZ_Alloc (&cmd_text, 32768, "command buffer"); // space for commands and script files
-}
-
+static sizebuf_t cmd_text;
+static qbyte cmd_text_buf[32768];
/*
============
{
int l;
- l = strlen (text);
+ l = (int)strlen (text);
if (cmd_text.cursize + l >= cmd_text.maxsize)
{
return;
}
- SZ_Write (&cmd_text, text, strlen (text));
+ SZ_Write (&cmd_text, text, (int)strlen (text));
}
char *temp;
int templen;
-// copy off any commands still remaining in the exec buffer
+ // copy off any commands still remaining in the exec buffer
templen = cmd_text.cursize;
if (templen)
{
- temp = Z_Malloc (templen);
+ temp = Mem_Alloc (tempmempool, templen);
memcpy (temp, cmd_text.data, templen);
SZ_Clear (&cmd_text);
}
else
- temp = NULL; // shut up compiler
+ temp = NULL;
-// add the entire text of the file
+ // add the entire text of the file
Cbuf_AddText (text);
-// add the copied off data
- if (templen)
+ // add the copied off data
+ if (temp != NULL)
{
SZ_Write (&cmd_text, temp, templen);
- Z_Free (temp);
+ Mem_Free (temp);
}
}
for (i=0 ; i< cmd_text.cursize ; i++)
{
if (text[i] == '"')
- quotes++;
- if ( !(quotes&1) && text[i] == ';')
+ quotes ^= 1;
+ if ( !quotes && text[i] == ';')
break; // don't break if inside a quoted string
if (text[i] == '\r' || text[i] == '\n')
break;
quake -nosound +cmd amlev1
===============
*/
+qboolean host_stuffcmdsrun = false;
void Cmd_StuffCmds_f (void)
{
- int i, j;
- int s;
- char *text, *build, c;
+ int i, j, l;
+ // this is per command, and bounds checked (no buffer overflows)
+ char build[2048];
if (Cmd_Argc () != 1)
{
return;
}
-// build the combined string to parse from
- s = 0;
- for (i=1 ; i<com_argc ; i++)
- {
- if (!com_argv[i])
- continue; // NEXTSTEP nulls out -NXHost
- s += strlen (com_argv[i]) + 1;
- }
- if (!s)
- return;
-
- text = Z_Malloc (s+1);
- text[0] = 0;
- for (i=1 ; i<com_argc ; i++)
- {
- if (!com_argv[i])
- continue; // NEXTSTEP nulls out -NXHost
- strcat (text,com_argv[i]);
- if (i != com_argc-1)
- strcat (text, " ");
- }
-
-// pull out the commands
- build = Z_Malloc (s+1);
- build[0] = 0;
-
- for (i=0 ; i<s-1 ; i++)
+ host_stuffcmdsrun = true;
+ for (i = 0;i < com_argc;i++)
{
- if (text[i] == '+')
+ if (com_argv[i] && com_argv[i][0] == '+' && (com_argv[i][1] < '0' || com_argv[i][1] > '9'))
{
+ l = 0;
+ j = 1;
+ while (com_argv[i][j])
+ build[l++] = com_argv[i][j++];
i++;
-
- for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
- ;
-
- c = text[j];
- text[j] = 0;
-
- strcat (build, text+i);
- strcat (build, "\n");
- text[j] = c;
- i = j-1;
+ for (;i < com_argc;i++)
+ {
+ if (!com_argv[i])
+ continue;
+ if ((com_argv[i][0] == '+' || com_argv[i][0] == '-') && (com_argv[i][1] < '0' || com_argv[i][1] > '9'))
+ break;
+ if (l + strlen(com_argv[i]) + 5 > sizeof(build))
+ break;
+ build[l++] = ' ';
+ build[l++] = '\"';
+ for (j = 0;com_argv[i][j];j++)
+ build[l++] = com_argv[i][j];
+ build[l++] = '\"';
+ }
+ build[l++] = '\n';
+ build[l++] = 0;
+ Cbuf_InsertText (build);
+ i--;
}
}
-
- if (build[0])
- Cbuf_InsertText (build);
-
- Z_Free (text);
- Z_Free (build);
}
return;
}
- f = (char *)FS_LoadFile (Cmd_Argv(1), false);
+ f = (char *)FS_LoadFile (Cmd_Argv(1), tempmempool, false);
if (!f)
{
Con_Printf("couldn't exec %s\n",Cmd_Argv(1));
Creates a new command that executes a command string (possibly ; seperated)
===============
*/
-static char *CopyString (char *in)
-{
- char *out;
-
- out = Z_Malloc (strlen(in)+1);
- strcpy (out, in);
- return out;
-}
-
static void Cmd_Alias_f (void)
{
cmdalias_t *a;
if (!a)
{
+ cmdalias_t *prev, *current;
+
a = Z_Malloc (sizeof(cmdalias_t));
- a->next = cmd_alias;
- cmd_alias = a;
+ strlcpy (a->name, s, sizeof (a->name));
+ // insert it at the right alphanumeric position
+ for( prev = NULL, current = cmd_alias ; current && strcmp( current->name, a->name ) < 0 ; prev = current, current = current->next )
+ ;
+ if( prev ) {
+ prev->next = a;
+ } else {
+ cmd_alias = a;
+ }
+ a->next = current;
}
- strlcpy (a->name, s, sizeof (a->name));
+
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
}
strlcat (cmd, "\n", sizeof (cmd));
- a->value = CopyString (cmd);
+ a->value = Z_Malloc (strlen (cmd) + 1);
+ strcpy (a->value, cmd);
}
/*
static cmd_function_t *cmd_functions; // possible commands to execute
+/*
+============
+Cmd_ExecuteAlias
+
+Called for aliases and fills in the alias into the cbuffer
+============
+*/
+static void Cmd_ExecuteAlias (cmdalias_t *alias)
+{
+#define ALIAS_BUFFER 1024
+ static char buffer[ ALIAS_BUFFER + 2 ];
+ const char *in;
+ char *out;
+ unsigned outlen;
+ int inquote;
+
+ in = alias->value;
+ out = buffer;
+ outlen = 0;
+ inquote = 0;
+
+ while( *in && outlen < ALIAS_BUFFER )
+ {
+ if( *in == '"' )
+ {
+ inquote ^= 1;
+ }
+ else if( *in == '$' && !inquote )
+ {
+ // $* is replaced with all formal parameters, $num is parsed as an argument (or as $num if there arent enough parameters), $bla becomes $bla and $$bla becomes $$bla
+ // read over the $
+ in++;
+ if( *in == '*' )
+ {
+ const char *linein = Cmd_Args();
+ // include all params
+ while( *linein && outlen < ALIAS_BUFFER ) {
+ *out++ = *linein++;
+ outlen++;
+ }
+
+ in++;
+ } else {
+ char *nexttoken;
+ int argnum;
+
+ argnum = strtol( in, &nexttoken, 10 );
+
+ if( 0 < argnum && argnum < Cmd_Argc() )
+ {
+ const char *param = Cmd_Argv( argnum );
+ while( *param && outlen < ALIAS_BUFFER ) {
+ *out++ = *param++;
+ outlen++;
+ }
+ in = nexttoken;
+ }
+ else if( argnum >= Cmd_Argc() )
+ {
+ Con_Printf( "Warning: Not enough parameters passed to alias '%s', at least %i expected:\n %s\n", alias->name, argnum, alias->value );
+ *out++ = '$';
+ outlen++;
+ }
+ // not a number
+ else if( argnum == 0 )
+ {
+ *out++ = '$';
+ outlen++;
+ }
+ }
+ } else {
+ *out++ = *in++;
+ outlen++;
+ }
+ }
+ *out++ = '\n';
+ *out++ = 0;
+ Cbuf_AddText( buffer );
+}
+
/*
========
Cmd_List
if (Cmd_Argc() > 1)
{
partial = Cmd_Argv (1);
- len = strlen(partial);
+ len = (int)strlen(partial);
}
else
{
*/
void Cmd_Init (void)
{
- cmd_mempool = Mem_AllocPool("commands");
+ cmd_mempool = Mem_AllocPool("commands", 0, NULL);
+ // space for commands and script files
+ cmd_text.data = cmd_text_buf;
+ cmd_text.maxsize = sizeof(cmd_text_buf);
+ cmd_text.cursize = 0;
+}
+void Cmd_Init_Commands (void)
+{
//
// register our commands
//
Cmd_AddCommand ("cmdlist", Cmd_List_f); // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
Cmd_AddCommand ("cvarlist", Cvar_List_f); // 2000-01-09 CmdList, CvarList commands
// By Matthias "Maddes" Buecher
+ Cmd_AddCommand ("set", Cvar_Set_f);
+ Cmd_AddCommand ("seta", Cvar_SetA_f);
+}
+
+/*
+============
+Cmd_Shutdown
+============
+*/
+void Cmd_Shutdown(void)
+{
+ Mem_FreePool(&cmd_mempool);
}
/*
while (1)
{
// skip whitespace up to a /n
- while (*text && *text <= ' ' && *text != '\n')
+ while (*text && *text <= ' ' && *text != '\r' && *text != '\n')
text++;
- if (*text == '\n')
+ // line endings:
+ // UNIX: \n
+ // Mac: \r
+ // Windows: \r\n
+ if (*text == '\n' || *text == '\r')
{
// a newline seperates commands in the buffer
+ if (*text == '\r' && text[1] == '\n')
+ text++;
text++;
break;
}
if (!COM_ParseTokenConsole(&text))
return;
+ // check for $cvar
+ // (perhaps use another target buffer?)
+ if (com_token[0] == '$' && com_token[1])
+ {
+ cvar_t *cvar;
+
+ cvar = Cvar_FindVar(&com_token[1]);
+ if (cvar)
+ {
+ strcpy(com_token, cvar->string);
+ }
+ else if( com_token[1] == '$' )
+ {
+ // remove the first $
+ char *pos;
+
+ for( pos = com_token ; *pos ; pos++ )
+ {
+ *pos = *(pos + 1);
+ }
+ }
+ }
+
if (cmd_argc < MAX_ARGS)
{
- l = strlen(com_token) + 1;
+ l = (int)strlen(com_token) + 1;
if (cmd_tokenizebufferpos + l > CMD_TOKENIZELENGTH)
- Sys_Error("Cmd_TokenizeString: ran out of %i character buffer space for command arguements\n", CMD_TOKENIZELENGTH);
+ {
+ Con_Printf("Cmd_TokenizeString: ran out of %i character buffer space for command arguements\n", CMD_TOKENIZELENGTH);
+ break;
+ }
strcpy (cmd_tokenizebuffer + cmd_tokenizebufferpos, com_token);
cmd_argv[cmd_argc] = cmd_tokenizebuffer + cmd_tokenizebufferpos;
cmd_tokenizebufferpos += l;
cmd_argc++;
}
}
-
}
void Cmd_AddCommand (const char *cmd_name, xcommand_t function)
{
cmd_function_t *cmd;
+ cmd_function_t *prev, *current;
// fail if the command is a variable name
- if (Cvar_VariableString(cmd_name)[0])
+ if (Cvar_FindVar( cmd_name ))
{
Con_Printf("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
return;
cmd->name = cmd_name;
cmd->function = function;
cmd->next = cmd_functions;
- cmd_functions = cmd;
+
+// insert it at the right alphanumeric position
+ for( prev = NULL, current = cmd_functions ; current && strcmp( current->name, cmd->name ) < 0 ; prev = current, current = current->next )
+ ;
+ if( prev ) {
+ prev->next = cmd;
+ } else {
+ cmd_functions = cmd;
+ }
+ cmd->next = current;
}
/*
const char *Cmd_CompleteCommand (const char *partial)
{
cmd_function_t *cmd;
- int len;
+ size_t len;
len = strlen(partial);
int Cmd_CompleteCountPossible (const char *partial)
{
cmd_function_t *cmd;
- int len, h;
+ size_t len;
+ int h;
h = 0;
len = strlen(partial);
const char **Cmd_CompleteBuildList (const char *partial)
{
cmd_function_t *cmd;
- int len = 0;
- int bpos = 0;
- int sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (const char *);
+ size_t len = 0;
+ size_t bpos = 0;
+ size_t sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (const char *);
const char **buf;
len = strlen(partial);
const char *Cmd_CompleteAlias (const char *partial)
{
cmdalias_t *alias;
- int len;
+ size_t len;
len = strlen(partial);
int Cmd_CompleteAliasCountPossible (const char *partial)
{
cmdalias_t *alias;
- int len;
+ size_t len;
int h;
h = 0;
const char **Cmd_CompleteAliasBuildList (const char *partial)
{
cmdalias_t *alias;
- int len = 0;
- int bpos = 0;
- int sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (const char *);
+ size_t len = 0;
+ size_t bpos = 0;
+ size_t sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (const char *);
const char **buf;
len = strlen(partial);
return; // no tokens
}
-// check functions (only after host_initialized)
- if (host_initialized || !strcasecmp(cmd_argv[0], "exec"))
+// check functions
+ for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
{
- for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+ if (!strcasecmp (cmd_argv[0],cmd->name))
{
- if (!strcasecmp (cmd_argv[0],cmd->name))
- {
- cmd->function ();
- cmd_tokenizebufferpos = oldpos;
- return;
- }
+ cmd->function ();
+ cmd_tokenizebufferpos = oldpos;
+ return;
}
}
-// check alias (only after host_initialized)
- if (host_initialized)
+// check alias
+ for (a=cmd_alias ; a ; a=a->next)
{
- for (a=cmd_alias ; a ; a=a->next)
+ if (!strcasecmp (cmd_argv[0], a->name))
{
- if (!strcasecmp (cmd_argv[0], a->name))
- {
- Cbuf_InsertText (a->value);
- cmd_tokenizebufferpos = oldpos;
- return;
- }
+ Cmd_ExecuteAlias(a);
+ cmd_tokenizebufferpos = oldpos;
+ return;
}
}
-// check cvars (always)
- if (!Cvar_Command () && host_initialized)
+// check cvars
+ if (!Cvar_Command () && host_framecount > 0)
Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(0));
cmd_tokenizebufferpos = oldpos;
/*
===================
-Cmd_ForwardToServer
+Cmd_ForwardStringToServer
-Sends the entire command line over to the server
+Sends an entire command string over to the server, unprocessed
===================
*/
-void Cmd_ForwardToServer (void)
+void Cmd_ForwardStringToServer (const char *s)
{
- const char *s;
if (cls.state != ca_connected)
{
- Con_Printf("Can't \"%s\", not connected\n", Cmd_Argv(0));
+ Con_Printf("Can't \"%s\", not connected\n", s);
return;
}
// LordHavoc: thanks to Fuh for bringing the pure evil of SZ_Print to my
// attention, it has been eradicated from here, its only (former) use in
// all of darkplaces.
- if (strcasecmp(Cmd_Argv(0), "cmd") != 0)
- s = va("%s %s", Cmd_Argv(0), Cmd_Argc() > 1 ? Cmd_Args() : "\n");
- else
- s = Cmd_Argc() > 1 ? Cmd_Args() : "\n";
MSG_WriteByte(&cls.message, clc_stringcmd);
- SZ_Write(&cls.message, s, strlen(s) + 1);
+ SZ_Write(&cls.message, s, (int)strlen(s) + 1);
+}
+
+/*
+===================
+Cmd_ForwardToServer
+
+Sends the entire command line over to the server
+===================
+*/
+void Cmd_ForwardToServer (void)
+{
+ const char *s;
+ if (!strcasecmp(Cmd_Argv(0), "cmd"))
+ {
+ // we want to strip off "cmd", so just send the args
+ s = Cmd_Argc() > 1 ? Cmd_Args() : "";
+ }
+ else
+ {
+ // we need to keep the command name, so send Cmd_Argv(0), a space and then Cmd_Args()
+ s = va("%s %s", Cmd_Argv(0), Cmd_Argc() > 1 ? Cmd_Args() : "");
+ }
+ // don't send an empty forward message if the user tries "cmd" by itself
+ if (!s || !*s)
+ return;
+ Cmd_ForwardStringToServer(s);
}
int i;
if (!parm)
- Sys_Error ("Cmd_CheckParm: NULL");
+ {
+ Con_Printf ("Cmd_CheckParm: NULL");
+ return 0;
+ }
for (i = 1; i < Cmd_Argc (); i++)
if (!strcasecmp (parm, Cmd_Argv (i)))