Annotation of quake2/qcommon/cmd.c, revision 1.1.1.1

1.1       root        1: // cmd.c -- Quake script command processing module
                      2: #include "qcommon.h"
                      3: void Cmd_ForwardToServer (void);
                      4: #define        MAX_ALIAS_NAME  32
                      5: typedef struct cmdalias_s
                      6: {
                      7:        struct cmdalias_s       *next;
                      8:        char    name[MAX_ALIAS_NAME];
                      9:        char    *value;
                     10: } cmdalias_t;
                     11: cmdalias_t     *cmd_alias;
                     12: qboolean       cmd_wait;
                     13: #define        ALIAS_LOOP_COUNT        16
                     14: int            alias_count;            // for detecting runaway loops
                     15: //=============================================================================
                     16: /*
                     17: ============
                     18: Cmd_Wait_f
                     19: Causes execution of the remainder of the command buffer to be delayed until
                     20: next frame.  This allows commands like:
                     21: bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
                     22: ============
                     23: */
                     24: void Cmd_Wait_f (void)
                     25: {
                     26:        cmd_wait = true;
                     27: }
                     28: 
                     29: /*
                     30: =============================================================================
                     31:                                                COMMAND BUFFER
                     32: =============================================================================
                     33: */
                     34: sizebuf_t      cmd_text;
                     35: byte           cmd_text_buf[8192];
                     36: 
                     37: byte           defer_text_buf[8192];
                     38: /*
                     39: ============
                     40: Cbuf_Init
                     41: ============
                     42: */
                     43: void Cbuf_Init (void)
                     44: {
                     45:        SZ_Init (&cmd_text, cmd_text_buf, sizeof(cmd_text_buf));
                     46: }
                     47: 
                     48: /*
                     49: ============
                     50: Cbuf_AddText
                     51: Adds command text at the end of the buffer
                     52: ============
                     53: */
                     54: void Cbuf_AddText (char *text)
                     55: {
                     56:        int             l;
                     57:        
                     58:        l = strlen (text);
                     59:        if (cmd_text.cursize + l >= cmd_text.maxsize)
                     60:        {
                     61:                Com_Printf ("Cbuf_AddText: overflow\n");
                     62:                return;
                     63:        }
                     64:        SZ_Write (&cmd_text, text, strlen (text));
                     65: }
                     66: /*
                     67: ============
                     68: Cbuf_InsertText
                     69: Adds command text immediately after the current command
                     70: Adds a \n to the text
                     71: FIXME: actually change the command buffer to do less copying
                     72: ============
                     73: */
                     74: void Cbuf_InsertText (char *text)
                     75: {
                     76:        char    *temp;
                     77:        int             templen;
                     78: // copy off any commands still remaining in the exec buffer
                     79:        templen = cmd_text.cursize;
                     80:        if (templen)
                     81:        {
                     82:                temp = Z_Malloc (templen);
                     83:                memcpy (temp, cmd_text.data, templen);
                     84:                SZ_Clear (&cmd_text);
                     85:        }
                     86:        else
                     87:                temp = NULL;    // shut up compiler
                     88:                
                     89: // add the entire text of the file
                     90:        Cbuf_AddText (text);
                     91:        
                     92: // add the copied off data
                     93:        if (templen)
                     94:        {
                     95:                SZ_Write (&cmd_text, temp, templen);
                     96:                Z_Free (temp);
                     97:        }
                     98: }
                     99: 
                    100: /*
                    101: ============
                    102: Cbuf_CopyToDefer
                    103: ============
                    104: */
                    105: void Cbuf_CopyToDefer (void)
                    106: {
                    107:        memcpy(defer_text_buf, cmd_text_buf, cmd_text.cursize);
                    108:        defer_text_buf[cmd_text.cursize] = 0;
                    109:        cmd_text.cursize = 0;
                    110: }
                    111: 
                    112: /*
                    113: ============
                    114: Cbuf_InsertFromDefer
                    115: ============
                    116: */
                    117: void Cbuf_InsertFromDefer (void)
                    118: {
                    119:        Cbuf_InsertText (defer_text_buf);
                    120:        defer_text_buf[0] = 0;
                    121: }
                    122: 
                    123: 
                    124: /*
                    125: ============
                    126: Cbuf_ExecuteText
                    127: ============
                    128: */
                    129: void Cbuf_ExecuteText (int exec_when, char *text)
                    130: {
                    131:        switch (exec_when)
                    132:        {
                    133:        case EXEC_NOW:
                    134:                Cmd_ExecuteString (text);
                    135:                break;
                    136:        case EXEC_INSERT:
                    137:                Cbuf_InsertText (text);
                    138:                break;
                    139:        case EXEC_APPEND:
                    140:                Cbuf_AddText (text);
                    141:                break;
                    142:        default:
                    143:                Com_Error (ERR_FATAL, "Cbuf_ExecuteText: bad exec_when");
                    144:        }
                    145: }
                    146: /*
                    147: ============
                    148: Cbuf_Execute
                    149: ============
                    150: */
                    151: void Cbuf_Execute (void)
                    152: {
                    153:        int             i;
                    154:        char    *text;
                    155:        char    line[1024];
                    156:        int             quotes;
                    157: 
                    158:        alias_count = 0;                // don't allow infinite alias loops
                    159:        while (cmd_text.cursize)
                    160:        {
                    161: // find a \n or ; line break
                    162:                text = (char *)cmd_text.data;
                    163:                quotes = 0;
                    164:                for (i=0 ; i< cmd_text.cursize ; i++)
                    165:                {
                    166:                        if (text[i] == '"')
                    167:                                quotes++;
                    168:                        if ( !(quotes&1) &&  text[i] == ';')
                    169:                                break;  // don't break if inside a quoted string
                    170:                        if (text[i] == '\n')
                    171:                                break;
                    172:                }
                    173:                        
                    174:                                
                    175:                memcpy (line, text, i);
                    176:                line[i] = 0;
                    177:                
                    178: // delete the text from the command buffer and move remaining commands down
                    179: // this is necessary because commands (exec, alias) can insert data at the
                    180: // beginning of the text buffer
                    181:                if (i == cmd_text.cursize)
                    182:                        cmd_text.cursize = 0;
                    183:                else
                    184:                {
                    185:                        i++;
                    186:                        cmd_text.cursize -= i;
                    187:                        memmove (text, text+i, cmd_text.cursize);
                    188:                }
                    189: // execute the command line
                    190:                Cmd_ExecuteString (line);
                    191:                
                    192:                if (cmd_wait)
                    193:                {
                    194:                        // skip out while text still remains in buffer, leaving it
                    195:                        // for next frame
                    196:                        cmd_wait = false;
                    197:                        break;
                    198:                }
                    199:        }
                    200: }
                    201: /*
                    202: ===============
                    203: Cbuf_AddEarlyCommands
                    204: Adds command line parameters as script statements
                    205: Commands lead with a +, and continue until another +
                    206: Set commands are added early, so they are guaranteed to be set before
                    207: the client and server initialize for the first time.
                    208: Other commands are added late, after all initialization is complete.
                    209: ===============
                    210: */
                    211: void Cbuf_AddEarlyCommands (qboolean clear)
                    212: {
                    213:        int             i;
                    214:        char    *s;
                    215:        for (i=0 ; i<COM_Argc() ; i++)
                    216:        {
                    217:                s = COM_Argv(i);
                    218:                if (strcmp (s, "+set"))
                    219:                        continue;
                    220:                Cbuf_AddText (va("set %s %s\n", COM_Argv(i+1), COM_Argv(i+2)));
                    221:                if (clear)
                    222:                {
                    223:                        COM_ClearArgv(i);
                    224:                        COM_ClearArgv(i+1);
                    225:                        COM_ClearArgv(i+2);
                    226:                }
                    227:                i+=2;
                    228:        }
                    229: }
                    230: /*
                    231: =================
                    232: Cbuf_AddLateCommands
                    233: Adds command line parameters as script statements
                    234: Commands lead with a + and continue until another + or -
                    235: quake +vid_ref gl +map amlev1
                    236: Returns true if any late commands were added, which
                    237: will keep the demoloop from immediately starting
                    238: =================
                    239: */
                    240: qboolean Cbuf_AddLateCommands (void)
                    241: {
                    242:        int             i, j;
                    243:        int             s;
                    244:        char    *text, *build, c;
                    245:        int             argc;
                    246:        qboolean        ret;
                    247: // build the combined string to parse from
                    248:        s = 0;
                    249:        argc = COM_Argc();
                    250:        for (i=1 ; i<argc ; i++)
                    251:        {
                    252:                s += strlen (COM_Argv(i)) + 1;
                    253:        }
                    254:        if (!s)
                    255:                return false;
                    256:                
                    257:        text = Z_Malloc (s+1);
                    258:        text[0] = 0;
                    259:        for (i=1 ; i<argc ; i++)
                    260:        {
                    261:                strcat (text,COM_Argv(i));
                    262:                if (i != argc-1)
                    263:                        strcat (text, " ");
                    264:        }
                    265:        
                    266: // pull out the commands
                    267:        build = Z_Malloc (s+1);
                    268:        build[0] = 0;
                    269:        
                    270:        for (i=0 ; i<s-1 ; i++)
                    271:        {
                    272:                if (text[i] == '+')
                    273:                {
                    274:                        i++;
                    275:                        for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
                    276:                                ;
                    277:                        c = text[j];
                    278:                        text[j] = 0;
                    279:                        
                    280:                        strcat (build, text+i);
                    281:                        strcat (build, "\n");
                    282:                        text[j] = c;
                    283:                        i = j-1;
                    284:                }
                    285:        }
                    286:        ret = (build[0] != 0);
                    287:        if (ret)
                    288:                Cbuf_AddText (build);
                    289:        
                    290:        Z_Free (text);
                    291:        Z_Free (build);
                    292:        return ret;
                    293: }
                    294: /*
                    295: ==============================================================================
                    296:                                                SCRIPT COMMANDS
                    297: ==============================================================================
                    298: */
                    299: /*
                    300: ===============
                    301: Cmd_Exec_f
                    302: ===============
                    303: */
                    304: void Cmd_Exec_f (void)
                    305: {
                    306:        char    *f, *f2;
                    307:        int             len;
                    308:        if (Cmd_Argc () != 2)
                    309:        {
                    310:                Com_Printf ("exec <filename> : execute a script file\n");
                    311:                return;
                    312:        }
                    313:        len = FS_LoadFile (Cmd_Argv(1), (void **)&f);
                    314:        if (!f)
                    315:        {
                    316:                Com_Printf ("couldn't exec %s\n",Cmd_Argv(1));
                    317:                return;
                    318:        }
                    319:        Com_Printf ("execing %s\n",Cmd_Argv(1));
                    320:        
                    321:        // the file doesn't have a trailing 0, so we need to copy it off
                    322:        f2 = Z_Malloc(len+1);
                    323:        memcpy (f2, f, len);
                    324:        f2[len] = 0;
                    325:        Cbuf_InsertText (f2);
                    326:        Z_Free (f2);
                    327:        FS_FreeFile (f);
                    328: }
                    329: /*
                    330: ===============
                    331: Cmd_Echo_f
                    332: Just prints the rest of the line to the console
                    333: ===============
                    334: */
                    335: void Cmd_Echo_f (void)
                    336: {
                    337:        int             i;
                    338:        
                    339:        for (i=1 ; i<Cmd_Argc() ; i++)
                    340:                Com_Printf ("%s ",Cmd_Argv(i));
                    341:        Com_Printf ("\n");
                    342: }
                    343: /*
                    344: ===============
                    345: Cmd_Alias_f
                    346: Creates a new command that executes a command string (possibly ; seperated)
                    347: ===============
                    348: */
                    349: void Cmd_Alias_f (void)
                    350: {
                    351:        cmdalias_t      *a;
                    352:        char            cmd[1024];
                    353:        int                     i, c;
                    354:        char            *s;
                    355:        if (Cmd_Argc() == 1)
                    356:        {
                    357:                Com_Printf ("Current alias commands:\n");
                    358:                for (a = cmd_alias ; a ; a=a->next)
                    359:                        Com_Printf ("%s : %s\n", a->name, a->value);
                    360:                return;
                    361:        }
                    362:        s = Cmd_Argv(1);
                    363:        if (strlen(s) >= MAX_ALIAS_NAME)
                    364:        {
                    365:                Com_Printf ("Alias name is too long\n");
                    366:                return;
                    367:        }
                    368:        // if the alias already exists, reuse it
                    369:        for (a = cmd_alias ; a ; a=a->next)
                    370:        {
                    371:                if (!strcmp(s, a->name))
                    372:                {
                    373:                        Z_Free (a->value);
                    374:                        break;
                    375:                }
                    376:        }
                    377:        if (!a)
                    378:        {
                    379:                a = Z_Malloc (sizeof(cmdalias_t));
                    380:                a->next = cmd_alias;
                    381:                cmd_alias = a;
                    382:        }
                    383:        strcpy (a->name, s);    
                    384: // copy the rest of the command line
                    385:        cmd[0] = 0;             // start out with a null string
                    386:        c = Cmd_Argc();
                    387:        for (i=2 ; i< c ; i++)
                    388:        {
                    389:                strcat (cmd, Cmd_Argv(i));
                    390:                if (i != (c - 1))
                    391:                        strcat (cmd, " ");
                    392:        }
                    393:        strcat (cmd, "\n");
                    394:        
                    395:        a->value = CopyString (cmd);
                    396: }
                    397: /*
                    398: =============================================================================
                    399:                                        COMMAND EXECUTION
                    400: =============================================================================
                    401: */
                    402: typedef struct cmd_function_s
                    403: {
                    404:        struct cmd_function_s   *next;
                    405:        char                                    *name;
                    406:        xcommand_t                              function;
                    407: } cmd_function_t;
                    408: static int                     cmd_argc;
                    409: static char            *cmd_argv[MAX_STRING_TOKENS];
                    410: static char            *cmd_null_string = "";
                    411: static char            cmd_args[MAX_STRING_CHARS];
                    412: static cmd_function_t  *cmd_functions;         // possible commands to execute
                    413: /*
                    414: ============
                    415: Cmd_Argc
                    416: ============
                    417: */
                    418: int            Cmd_Argc (void)
                    419: {
                    420:        return cmd_argc;
                    421: }
                    422: /*
                    423: ============
                    424: Cmd_Argv
                    425: ============
                    426: */
                    427: char   *Cmd_Argv (int arg)
                    428: {
                    429:        if ( (unsigned)arg >= cmd_argc )
                    430:                return cmd_null_string;
                    431:        return cmd_argv[arg];   
                    432: }
                    433: /*
                    434: ============
                    435: Cmd_Args
                    436: Returns a single string containing argv(1) to argv(argc()-1)
                    437: ============
                    438: */
                    439: char           *Cmd_Args (void)
                    440: {
                    441:        return cmd_args;
                    442: }
                    443: /*
                    444: ======================
                    445: Cmd_MacroExpandString
                    446: ======================
                    447: */
                    448: char *Cmd_MacroExpandString (char *text)
                    449: {
                    450:        int             i, j, count, len;
                    451:        qboolean        inquote;
                    452:        char    *scan;
                    453:        static  char    expanded[MAX_STRING_CHARS];
                    454:        char    temporary[MAX_STRING_CHARS];
                    455:        char    *token, *start;
                    456: 
                    457:        inquote = false;
                    458:        scan = text;
                    459: 
                    460:        len = strlen (scan);
                    461:        if (len >= MAX_STRING_CHARS)
                    462:        {
                    463:                Com_Printf ("Line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
                    464:                return NULL;
                    465:        }
                    466: 
                    467:        count = 0;
                    468: 
                    469:        for (i=0 ; i<len ; i++)
                    470:        {
                    471:                if (scan[i] == '"')
                    472:                        inquote ^= 1;
                    473:                if (inquote)
                    474:                        continue;       // don't expand inside quotes
                    475:                if (scan[i] != '$')
                    476:                        continue;
                    477:                // scan out the complete macro
                    478:                start = scan+i+1;
                    479:                token = COM_Parse (&start);
                    480:                if (!start)
                    481:                        continue;
                    482:        
                    483:                token = Cvar_VariableString (token);
                    484: 
                    485:                j = strlen(token);
                    486:                len += j;
                    487:                if (len >= MAX_STRING_CHARS)
                    488:                {
                    489:                        Com_Printf ("Expanded line exceeded %i chars, discarded.\n", MAX_STRING_CHARS);
                    490:                        return NULL;
                    491:                }
                    492: 
                    493:                strncpy (temporary, scan, i);
                    494:                strcpy (temporary+i, token);
                    495:                strcpy (temporary+i+j, start);
                    496: 
                    497:                strcpy (expanded, temporary);
                    498:                scan = expanded;
                    499:                i--;
                    500: 
                    501:                if (++count == 100)
                    502:                {
                    503:                        Com_Printf ("Macro expansion loop, discarded.\n");
                    504:                        return NULL;
                    505:                }
                    506:        }
                    507: 
                    508:        if (inquote)
                    509:        {
                    510:                Com_Printf ("Line has unmatched quote, discarded.\n");
                    511:                return NULL;
                    512:        }
                    513: 
                    514:        return scan;
                    515: }
                    516: 
                    517: 
                    518: /*
                    519: ============
                    520: Cmd_TokenizeString
                    521: Parses the given string into command line tokens.
                    522: $Cvars will be expanded unless they are in a quoted token
                    523: ============
                    524: */
                    525: void Cmd_TokenizeString (char *text, qboolean macroExpand)
                    526: {
                    527:        int             i;
                    528:        char    *com_token;
                    529: // clear the args from the last string
                    530:        for (i=0 ; i<cmd_argc ; i++)
                    531:                Z_Free (cmd_argv[i]);
                    532:                
                    533:        cmd_argc = 0;
                    534:        cmd_args[0] = 0;
                    535:        
                    536:        // macro expand the text
                    537:        if (macroExpand)
                    538:                text = Cmd_MacroExpandString (text);
                    539:        if (!text)
                    540:                return;
                    541:        while (1)
                    542:        {
                    543: // skip whitespace up to a /n
                    544:                while (*text && *text <= ' ' && *text != '\n')
                    545:                {
                    546:                        text++;
                    547:                }
                    548:                
                    549:                if (*text == '\n')
                    550:                {       // a newline seperates commands in the buffer
                    551:                        text++;
                    552:                        break;
                    553:                }
                    554:                if (!*text)
                    555:                        return;
                    556: 
                    557:                // set cmd_args to everything after the first arg
                    558:                if (cmd_argc == 1)
                    559:                {
                    560:                        int             l;
                    561: 
                    562:                        strcpy (cmd_args, text);
                    563: 
                    564:                        // strip off any trailing whitespace
                    565:                        l = strlen(cmd_args) - 1;
                    566:                        for ( ; l >= 0 ; l--)
                    567:                                if (cmd_args[l] <= ' ')
                    568:                                        cmd_args[l] = 0;
                    569:                                else
                    570:                                        break;
                    571:                }
                    572:                        
                    573:                com_token = COM_Parse (&text);
                    574:                if (!text)
                    575:                        return;
                    576:                if (cmd_argc < MAX_STRING_TOKENS)
                    577:                {
                    578:                        cmd_argv[cmd_argc] = Z_Malloc (strlen(com_token)+1);
                    579:                        strcpy (cmd_argv[cmd_argc], com_token);
                    580:                        cmd_argc++;
                    581:                }
                    582:        }
                    583:        
                    584: }
                    585: /*
                    586: ============
                    587: Cmd_AddCommand
                    588: ============
                    589: */
                    590: void   Cmd_AddCommand (char *cmd_name, xcommand_t function)
                    591: {
                    592:        cmd_function_t  *cmd;
                    593:        
                    594: // fail if the command is a variable name
                    595:        if (Cvar_VariableString(cmd_name)[0])
                    596:        {
                    597:                Com_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
                    598:                return;
                    599:        }
                    600:        
                    601: // fail if the command already exists
                    602:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    603:        {
                    604:                if (!strcmp (cmd_name, cmd->name))
                    605:                {
                    606:                        Com_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
                    607:                        return;
                    608:                }
                    609:        }
                    610:        cmd = Z_Malloc (sizeof(cmd_function_t));
                    611:        cmd->name = cmd_name;
                    612:        cmd->function = function;
                    613:        cmd->next = cmd_functions;
                    614:        cmd_functions = cmd;
                    615: }
                    616: /*
                    617: ============
                    618: Cmd_RemoveCommand
                    619: ============
                    620: */
                    621: void   Cmd_RemoveCommand (char *cmd_name)
                    622: {
                    623:        cmd_function_t  *cmd, **back;
                    624:        back = &cmd_functions;
                    625:        while (1)
                    626:        {
                    627:                cmd = *back;
                    628:                if (!cmd)
                    629:                {
                    630:                        Com_Printf ("Cmd_RemoveCommand: %s not added\n", cmd_name);
                    631:                        return;
                    632:                }
                    633:                if (!strcmp (cmd_name, cmd->name))
                    634:                {
                    635:                        *back = cmd->next;
                    636:                        Z_Free (cmd);
                    637:                        return;
                    638:                }
                    639:                back = &cmd->next;
                    640:        }
                    641: }
                    642: /*
                    643: ============
                    644: Cmd_Exists
                    645: ============
                    646: */
                    647: qboolean       Cmd_Exists (char *cmd_name)
                    648: {
                    649:        cmd_function_t  *cmd;
                    650:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    651:        {
                    652:                if (!strcmp (cmd_name,cmd->name))
                    653:                        return true;
                    654:        }
                    655:        return false;
                    656: }
                    657: /*
                    658: ============
                    659: Cmd_CompleteCommand
                    660: ============
                    661: */
                    662: char *Cmd_CompleteCommand (char *partial)
                    663: {
                    664:        cmd_function_t  *cmd;
                    665:        int                             len;
                    666:        cmdalias_t              *a;
                    667:        
                    668:        len = strlen(partial);
                    669:        
                    670:        if (!len)
                    671:                return NULL;
                    672:                
                    673: // check for exact match
                    674:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    675:                if (!strcmp (partial,cmd->name))
                    676:                        return cmd->name;
                    677:        for (a=cmd_alias ; a ; a=a->next)
                    678:                if (!strcmp (partial, a->name))
                    679:                        return a->name;
                    680: // check for partial match
                    681:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    682:                if (!strncmp (partial,cmd->name, len))
                    683:                        return cmd->name;
                    684:        for (a=cmd_alias ; a ; a=a->next)
                    685:                if (!strncmp (partial, a->name, len))
                    686:                        return a->name;
                    687:        return NULL;
                    688: }
                    689: /*
                    690: ============
                    691: Cmd_ExecuteString
                    692: A complete command line has been parsed, so try to execute it
                    693: FIXME: lookupnoadd the token to speed search?
                    694: ============
                    695: */
                    696: void   Cmd_ExecuteString (char *text)
                    697: {      
                    698:        cmd_function_t  *cmd;
                    699:        cmdalias_t              *a;
                    700:        Cmd_TokenizeString (text, true);
                    701:                        
                    702:        // execute the command line
                    703:        if (!Cmd_Argc())
                    704:                return;         // no tokens
                    705:        // check functions
                    706:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
                    707:        {
                    708:                if (!Q_strcasecmp (cmd_argv[0],cmd->name))
                    709:                {
                    710:                        if (!cmd->function)
                    711:                        {       // forward to server command
                    712:                                Cmd_ExecuteString (va("cmd %s", text));
                    713:                        }
                    714:                        else
                    715:                                cmd->function ();
                    716:                        return;
                    717:                }
                    718:        }
                    719:        // check alias
                    720:        for (a=cmd_alias ; a ; a=a->next)
                    721:        {
                    722:                if (!Q_strcasecmp (cmd_argv[0], a->name))
                    723:                {
                    724:                        if (++alias_count == ALIAS_LOOP_COUNT)
                    725:                        {
                    726:                                Com_Printf ("ALIAS_LOOP_COUNT\n");
                    727:                                return;
                    728:                        }
                    729:                        Cbuf_InsertText (a->value);
                    730:                        return;
                    731:                }
                    732:        }
                    733:        
                    734:        // check cvars
                    735:        if (Cvar_Command ())
                    736:                return;
                    737: 
                    738:        // send it as a server command if we are connected
                    739:        Cmd_ForwardToServer ();
                    740: }
                    741: /*
                    742: ============
                    743: Cmd_List_f
                    744: ============
                    745: */
                    746: void Cmd_List_f (void)
                    747: {
                    748:        cmd_function_t  *cmd;
                    749:        int                             i;
                    750:        i = 0;
                    751:        for (cmd=cmd_functions ; cmd ; cmd=cmd->next, i++)
                    752:                Com_Printf ("%s\n", cmd->name);
                    753:        Com_Printf ("%i commands\n", i);
                    754: }
                    755: /*
                    756: ============
                    757: Cmd_Init
                    758: ============
                    759: */
                    760: void Cmd_Init (void)
                    761: {
                    762: //
                    763: // register our commands
                    764: //
                    765:        Cmd_AddCommand ("cmdlist",Cmd_List_f);
                    766:        Cmd_AddCommand ("exec",Cmd_Exec_f);
                    767:        Cmd_AddCommand ("echo",Cmd_Echo_f);
                    768:        Cmd_AddCommand ("alias",Cmd_Alias_f);
                    769:        Cmd_AddCommand ("wait", Cmd_Wait_f);
                    770: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.