cmd.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // cmd.c -- Quake script command processing module
  19. #include "../game/q_shared.h"
  20. #include "qcommon.h"
  21. #define MAX_CMD_BUFFER 16384
  22. #define MAX_CMD_LINE 1024
  23. typedef struct {
  24. byte *data;
  25. int maxsize;
  26. int cursize;
  27. } cmd_t;
  28. int cmd_wait;
  29. cmd_t cmd_text;
  30. byte cmd_text_buf[MAX_CMD_BUFFER];
  31. //=============================================================================
  32. /*
  33. ============
  34. Cmd_Wait_f
  35. Causes execution of the remainder of the command buffer to be delayed until
  36. next frame. This allows commands like:
  37. bind g "cmd use rocket ; +attack ; wait ; -attack ; cmd use blaster"
  38. ============
  39. */
  40. void Cmd_Wait_f( void ) {
  41. if ( Cmd_Argc() == 2 ) {
  42. cmd_wait = atoi( Cmd_Argv( 1 ) );
  43. } else {
  44. cmd_wait = 1;
  45. }
  46. }
  47. /*
  48. =============================================================================
  49. COMMAND BUFFER
  50. =============================================================================
  51. */
  52. /*
  53. ============
  54. Cbuf_Init
  55. ============
  56. */
  57. void Cbuf_Init (void)
  58. {
  59. cmd_text.data = cmd_text_buf;
  60. cmd_text.maxsize = MAX_CMD_BUFFER;
  61. cmd_text.cursize = 0;
  62. }
  63. /*
  64. ============
  65. Cbuf_AddText
  66. Adds command text at the end of the buffer, does NOT add a final \n
  67. ============
  68. */
  69. void Cbuf_AddText( const char *text ) {
  70. int l;
  71. l = strlen (text);
  72. if (cmd_text.cursize + l >= cmd_text.maxsize)
  73. {
  74. Com_Printf ("Cbuf_AddText: overflow\n");
  75. return;
  76. }
  77. Com_Memcpy(&cmd_text.data[cmd_text.cursize], text, l);
  78. cmd_text.cursize += l;
  79. }
  80. /*
  81. ============
  82. Cbuf_InsertText
  83. Adds command text immediately after the current command
  84. Adds a \n to the text
  85. ============
  86. */
  87. void Cbuf_InsertText( const char *text ) {
  88. int len;
  89. int i;
  90. len = strlen( text ) + 1;
  91. if ( len + cmd_text.cursize > cmd_text.maxsize ) {
  92. Com_Printf( "Cbuf_InsertText overflowed\n" );
  93. return;
  94. }
  95. // move the existing command text
  96. for ( i = cmd_text.cursize - 1 ; i >= 0 ; i-- ) {
  97. cmd_text.data[ i + len ] = cmd_text.data[ i ];
  98. }
  99. // copy the new text in
  100. Com_Memcpy( cmd_text.data, text, len - 1 );
  101. // add a \n
  102. cmd_text.data[ len - 1 ] = '\n';
  103. cmd_text.cursize += len;
  104. }
  105. /*
  106. ============
  107. Cbuf_ExecuteText
  108. ============
  109. */
  110. void Cbuf_ExecuteText (int exec_when, const char *text)
  111. {
  112. switch (exec_when)
  113. {
  114. case EXEC_NOW:
  115. if (text && strlen(text) > 0) {
  116. Cmd_ExecuteString (text);
  117. } else {
  118. Cbuf_Execute();
  119. }
  120. break;
  121. case EXEC_INSERT:
  122. Cbuf_InsertText (text);
  123. break;
  124. case EXEC_APPEND:
  125. Cbuf_AddText (text);
  126. break;
  127. default:
  128. Com_Error (ERR_FATAL, "Cbuf_ExecuteText: bad exec_when");
  129. }
  130. }
  131. /*
  132. ============
  133. Cbuf_Execute
  134. ============
  135. */
  136. void Cbuf_Execute (void)
  137. {
  138. int i;
  139. char *text;
  140. char line[MAX_CMD_LINE];
  141. int quotes;
  142. while (cmd_text.cursize)
  143. {
  144. if ( cmd_wait ) {
  145. // skip out while text still remains in buffer, leaving it
  146. // for next frame
  147. cmd_wait--;
  148. break;
  149. }
  150. // find a \n or ; line break
  151. text = (char *)cmd_text.data;
  152. quotes = 0;
  153. for (i=0 ; i< cmd_text.cursize ; i++)
  154. {
  155. if (text[i] == '"')
  156. quotes++;
  157. if ( !(quotes&1) && text[i] == ';')
  158. break; // don't break if inside a quoted string
  159. if (text[i] == '\n' || text[i] == '\r' )
  160. break;
  161. }
  162. if( i >= (MAX_CMD_LINE - 1)) {
  163. i = MAX_CMD_LINE - 1;
  164. }
  165. Com_Memcpy (line, text, i);
  166. line[i] = 0;
  167. // delete the text from the command buffer and move remaining commands down
  168. // this is necessary because commands (exec) can insert data at the
  169. // beginning of the text buffer
  170. if (i == cmd_text.cursize)
  171. cmd_text.cursize = 0;
  172. else
  173. {
  174. i++;
  175. cmd_text.cursize -= i;
  176. memmove (text, text+i, cmd_text.cursize);
  177. }
  178. // execute the command line
  179. Cmd_ExecuteString (line);
  180. }
  181. }
  182. /*
  183. ==============================================================================
  184. SCRIPT COMMANDS
  185. ==============================================================================
  186. */
  187. /*
  188. ===============
  189. Cmd_Exec_f
  190. ===============
  191. */
  192. void Cmd_Exec_f( void ) {
  193. char *f;
  194. int len;
  195. char filename[MAX_QPATH];
  196. if (Cmd_Argc () != 2) {
  197. Com_Printf ("exec <filename> : execute a script file\n");
  198. return;
  199. }
  200. Q_strncpyz( filename, Cmd_Argv(1), sizeof( filename ) );
  201. COM_DefaultExtension( filename, sizeof( filename ), ".cfg" );
  202. len = FS_ReadFile( filename, (void **)&f);
  203. if (!f) {
  204. Com_Printf ("couldn't exec %s\n",Cmd_Argv(1));
  205. return;
  206. }
  207. Com_Printf ("execing %s\n",Cmd_Argv(1));
  208. Cbuf_InsertText (f);
  209. FS_FreeFile (f);
  210. }
  211. /*
  212. ===============
  213. Cmd_Vstr_f
  214. Inserts the current value of a variable as command text
  215. ===============
  216. */
  217. void Cmd_Vstr_f( void ) {
  218. char *v;
  219. if (Cmd_Argc () != 2) {
  220. Com_Printf ("vstr <variablename> : execute a variable command\n");
  221. return;
  222. }
  223. v = Cvar_VariableString( Cmd_Argv( 1 ) );
  224. Cbuf_InsertText( va("%s\n", v ) );
  225. }
  226. /*
  227. ===============
  228. Cmd_Echo_f
  229. Just prints the rest of the line to the console
  230. ===============
  231. */
  232. void Cmd_Echo_f (void)
  233. {
  234. int i;
  235. for (i=1 ; i<Cmd_Argc() ; i++)
  236. Com_Printf ("%s ",Cmd_Argv(i));
  237. Com_Printf ("\n");
  238. }
  239. /*
  240. =============================================================================
  241. COMMAND EXECUTION
  242. =============================================================================
  243. */
  244. typedef struct cmd_function_s
  245. {
  246. struct cmd_function_s *next;
  247. char *name;
  248. xcommand_t function;
  249. } cmd_function_t;
  250. static int cmd_argc;
  251. static char *cmd_argv[MAX_STRING_TOKENS]; // points into cmd_tokenized
  252. static char cmd_tokenized[BIG_INFO_STRING+MAX_STRING_TOKENS]; // will have 0 bytes inserted
  253. static char cmd_cmd[BIG_INFO_STRING]; // the original command we received (no token processing)
  254. static cmd_function_t *cmd_functions; // possible commands to execute
  255. /*
  256. ============
  257. Cmd_Argc
  258. ============
  259. */
  260. int Cmd_Argc( void ) {
  261. return cmd_argc;
  262. }
  263. /*
  264. ============
  265. Cmd_Argv
  266. ============
  267. */
  268. char *Cmd_Argv( int arg ) {
  269. if ( (unsigned)arg >= cmd_argc ) {
  270. return "";
  271. }
  272. return cmd_argv[arg];
  273. }
  274. /*
  275. ============
  276. Cmd_ArgvBuffer
  277. The interpreted versions use this because
  278. they can't have pointers returned to them
  279. ============
  280. */
  281. void Cmd_ArgvBuffer( int arg, char *buffer, int bufferLength ) {
  282. Q_strncpyz( buffer, Cmd_Argv( arg ), bufferLength );
  283. }
  284. /*
  285. ============
  286. Cmd_Args
  287. Returns a single string containing argv(1) to argv(argc()-1)
  288. ============
  289. */
  290. char *Cmd_Args( void ) {
  291. static char cmd_args[MAX_STRING_CHARS];
  292. int i;
  293. cmd_args[0] = 0;
  294. for ( i = 1 ; i < cmd_argc ; i++ ) {
  295. strcat( cmd_args, cmd_argv[i] );
  296. if ( i != cmd_argc-1 ) {
  297. strcat( cmd_args, " " );
  298. }
  299. }
  300. return cmd_args;
  301. }
  302. /*
  303. ============
  304. Cmd_Args
  305. Returns a single string containing argv(arg) to argv(argc()-1)
  306. ============
  307. */
  308. char *Cmd_ArgsFrom( int arg ) {
  309. static char cmd_args[BIG_INFO_STRING];
  310. int i;
  311. cmd_args[0] = 0;
  312. if (arg < 0)
  313. arg = 0;
  314. for ( i = arg ; i < cmd_argc ; i++ ) {
  315. strcat( cmd_args, cmd_argv[i] );
  316. if ( i != cmd_argc-1 ) {
  317. strcat( cmd_args, " " );
  318. }
  319. }
  320. return cmd_args;
  321. }
  322. /*
  323. ============
  324. Cmd_ArgsBuffer
  325. The interpreted versions use this because
  326. they can't have pointers returned to them
  327. ============
  328. */
  329. void Cmd_ArgsBuffer( char *buffer, int bufferLength ) {
  330. Q_strncpyz( buffer, Cmd_Args(), bufferLength );
  331. }
  332. /*
  333. ============
  334. Cmd_Cmd
  335. Retrieve the unmodified command string
  336. For rcon use when you want to transmit without altering quoting
  337. https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543
  338. ============
  339. */
  340. char *Cmd_Cmd()
  341. {
  342. return cmd_cmd;
  343. }
  344. /*
  345. ============
  346. Cmd_TokenizeString
  347. Parses the given string into command line tokens.
  348. The text is copied to a seperate buffer and 0 characters
  349. are inserted in the apropriate place, The argv array
  350. will point into this temporary buffer.
  351. ============
  352. */
  353. // NOTE TTimo define that to track tokenization issues
  354. //#define TKN_DBG
  355. void Cmd_TokenizeString( const char *text_in ) {
  356. const char *text;
  357. char *textOut;
  358. #ifdef TKN_DBG
  359. // FIXME TTimo blunt hook to try to find the tokenization of userinfo
  360. Com_DPrintf("Cmd_TokenizeString: %s\n", text_in);
  361. #endif
  362. // clear previous args
  363. cmd_argc = 0;
  364. if ( !text_in ) {
  365. return;
  366. }
  367. Q_strncpyz( cmd_cmd, text_in, sizeof(cmd_cmd) );
  368. text = text_in;
  369. textOut = cmd_tokenized;
  370. while ( 1 ) {
  371. if ( cmd_argc == MAX_STRING_TOKENS ) {
  372. return; // this is usually something malicious
  373. }
  374. while ( 1 ) {
  375. // skip whitespace
  376. while ( *text && *text <= ' ' ) {
  377. text++;
  378. }
  379. if ( !*text ) {
  380. return; // all tokens parsed
  381. }
  382. // skip // comments
  383. if ( text[0] == '/' && text[1] == '/' ) {
  384. return; // all tokens parsed
  385. }
  386. // skip /* */ comments
  387. if ( text[0] == '/' && text[1] =='*' ) {
  388. while ( *text && ( text[0] != '*' || text[1] != '/' ) ) {
  389. text++;
  390. }
  391. if ( !*text ) {
  392. return; // all tokens parsed
  393. }
  394. text += 2;
  395. } else {
  396. break; // we are ready to parse a token
  397. }
  398. }
  399. // handle quoted strings
  400. // NOTE TTimo this doesn't handle \" escaping
  401. if ( *text == '"' ) {
  402. cmd_argv[cmd_argc] = textOut;
  403. cmd_argc++;
  404. text++;
  405. while ( *text && *text != '"' ) {
  406. *textOut++ = *text++;
  407. }
  408. *textOut++ = 0;
  409. if ( !*text ) {
  410. return; // all tokens parsed
  411. }
  412. text++;
  413. continue;
  414. }
  415. // regular token
  416. cmd_argv[cmd_argc] = textOut;
  417. cmd_argc++;
  418. // skip until whitespace, quote, or command
  419. while ( *text > ' ' ) {
  420. if ( text[0] == '"' ) {
  421. break;
  422. }
  423. if ( text[0] == '/' && text[1] == '/' ) {
  424. break;
  425. }
  426. // skip /* */ comments
  427. if ( text[0] == '/' && text[1] =='*' ) {
  428. break;
  429. }
  430. *textOut++ = *text++;
  431. }
  432. *textOut++ = 0;
  433. if ( !*text ) {
  434. return; // all tokens parsed
  435. }
  436. }
  437. }
  438. /*
  439. ============
  440. Cmd_AddCommand
  441. ============
  442. */
  443. void Cmd_AddCommand( const char *cmd_name, xcommand_t function ) {
  444. cmd_function_t *cmd;
  445. // fail if the command already exists
  446. for ( cmd = cmd_functions ; cmd ; cmd=cmd->next ) {
  447. if ( !strcmp( cmd_name, cmd->name ) ) {
  448. // allow completion-only commands to be silently doubled
  449. if ( function != NULL ) {
  450. Com_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
  451. }
  452. return;
  453. }
  454. }
  455. // use a small malloc to avoid zone fragmentation
  456. cmd = S_Malloc (sizeof(cmd_function_t));
  457. cmd->name = CopyString( cmd_name );
  458. cmd->function = function;
  459. cmd->next = cmd_functions;
  460. cmd_functions = cmd;
  461. }
  462. /*
  463. ============
  464. Cmd_RemoveCommand
  465. ============
  466. */
  467. void Cmd_RemoveCommand( const char *cmd_name ) {
  468. cmd_function_t *cmd, **back;
  469. back = &cmd_functions;
  470. while( 1 ) {
  471. cmd = *back;
  472. if ( !cmd ) {
  473. // command wasn't active
  474. return;
  475. }
  476. if ( !strcmp( cmd_name, cmd->name ) ) {
  477. *back = cmd->next;
  478. if (cmd->name) {
  479. Z_Free(cmd->name);
  480. }
  481. Z_Free (cmd);
  482. return;
  483. }
  484. back = &cmd->next;
  485. }
  486. }
  487. /*
  488. ============
  489. Cmd_CommandCompletion
  490. ============
  491. */
  492. void Cmd_CommandCompletion( void(*callback)(const char *s) ) {
  493. cmd_function_t *cmd;
  494. for (cmd=cmd_functions ; cmd ; cmd=cmd->next) {
  495. callback( cmd->name );
  496. }
  497. }
  498. /*
  499. ============
  500. Cmd_ExecuteString
  501. A complete command line has been parsed, so try to execute it
  502. ============
  503. */
  504. void Cmd_ExecuteString( const char *text ) {
  505. cmd_function_t *cmd, **prev;
  506. // execute the command line
  507. Cmd_TokenizeString( text );
  508. if ( !Cmd_Argc() ) {
  509. return; // no tokens
  510. }
  511. // check registered command functions
  512. for ( prev = &cmd_functions ; *prev ; prev = &cmd->next ) {
  513. cmd = *prev;
  514. if ( !Q_stricmp( cmd_argv[0],cmd->name ) ) {
  515. // rearrange the links so that the command will be
  516. // near the head of the list next time it is used
  517. *prev = cmd->next;
  518. cmd->next = cmd_functions;
  519. cmd_functions = cmd;
  520. // perform the action
  521. if ( !cmd->function ) {
  522. // let the cgame or game handle it
  523. break;
  524. } else {
  525. cmd->function ();
  526. }
  527. return;
  528. }
  529. }
  530. // check cvars
  531. if ( Cvar_Command() ) {
  532. return;
  533. }
  534. // check client game commands
  535. if ( com_cl_running && com_cl_running->integer && CL_GameCommand() ) {
  536. return;
  537. }
  538. // check server game commands
  539. if ( com_sv_running && com_sv_running->integer && SV_GameCommand() ) {
  540. return;
  541. }
  542. // check ui commands
  543. if ( com_cl_running && com_cl_running->integer && UI_GameCommand() ) {
  544. return;
  545. }
  546. // send it as a server command if we are connected
  547. // this will usually result in a chat message
  548. CL_ForwardCommandToServer ( text );
  549. }
  550. /*
  551. ============
  552. Cmd_List_f
  553. ============
  554. */
  555. void Cmd_List_f (void)
  556. {
  557. cmd_function_t *cmd;
  558. int i;
  559. char *match;
  560. if ( Cmd_Argc() > 1 ) {
  561. match = Cmd_Argv( 1 );
  562. } else {
  563. match = NULL;
  564. }
  565. i = 0;
  566. for (cmd=cmd_functions ; cmd ; cmd=cmd->next) {
  567. if (match && !Com_Filter(match, cmd->name, qfalse)) continue;
  568. Com_Printf ("%s\n", cmd->name);
  569. i++;
  570. }
  571. Com_Printf ("%i commands\n", i);
  572. }
  573. /*
  574. ============
  575. Cmd_Init
  576. ============
  577. */
  578. void Cmd_Init (void) {
  579. Cmd_AddCommand ("cmdlist",Cmd_List_f);
  580. Cmd_AddCommand ("exec",Cmd_Exec_f);
  581. Cmd_AddCommand ("vstr",Cmd_Vstr_f);
  582. Cmd_AddCommand ("echo",Cmd_Echo_f);
  583. Cmd_AddCommand ("wait", Cmd_Wait_f);
  584. }