]> icculus.org git repositories - taylor/freespace2.git/blob - src/cmdline/cmdline.cpp
implemented a stub and fixed a path
[taylor/freespace2.git] / src / cmdline / cmdline.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Cmdline/cmdline.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * $Log$
16  * Revision 1.4  2002/06/21 03:34:05  relnev
17  * implemented a stub and fixed a path
18  *
19  * Revision 1.3  2002/06/09 04:41:15  relnev
20  * added copyright header
21  *
22  * Revision 1.2  2002/05/07 03:16:43  theoddone33
23  * The Great Newline Fix
24  *
25  * Revision 1.1.1.1  2002/05/03 03:28:08  root
26  * Initial import.
27  *
28  * 
29  * 8     8/26/99 8:51p Dave
30  * Gave multiplayer TvT messaging a heavy dose of sanity. Cheat codes.
31  * 
32  * 7     7/15/99 3:07p Dave
33  * 32 bit detection support. Mouse coord commandline.
34  * 
35  * 6     7/13/99 1:15p Dave
36  * 32 bit support. Whee!
37  * 
38  * 5     6/22/99 9:37p Dave
39  * Put in pof spewing.
40  * 
41  * 4     1/12/99 5:45p Dave
42  * Moved weapon pipeline in multiplayer to almost exclusively client side.
43  * Very good results. Bandwidth goes down, playability goes up for crappy
44  * connections. Fixed object update problem for ship subsystems.
45  * 
46  * 3     11/17/98 11:12a Dave
47  * Removed player identification by address. Now assign explicit id #'s.
48  * 
49  * 2     10/07/98 10:52a Dave
50  * Initial checkin.
51  * 
52  * 1     10/07/98 10:48a Dave
53  * 
54  * 38    10/02/98 3:22p Allender
55  * fix up the -connect option and fix the -port option
56  * 
57  * 37    9/15/98 4:04p Allender
58  * added back in the -ip_addr command line switch because it needs to be
59  * in the standalone server only executable
60  * 
61  * 36    9/14/98 11:52a Allender
62  * don't use cfile
63  * 
64  * 35    9/14/98 11:28a Allender
65  * support for server bashing of address when received from client.  Added
66  * a cmdline.cfg file to process command line arguments from a file
67  * 
68  * 34    9/08/98 2:20p Allender
69  * temporary code to force IP address to a specific value.
70  * 
71  * 33    8/20/98 5:30p Dave
72  * Put in handy multiplayer logfile system. Now need to put in useful
73  * applications of it all over the code.
74  * 
75  * 32    8/07/98 10:39a Allender
76  * fixed debug standalone problem where stats would continually get sent
77  * to tracker.  more debug code to help find stats problem
78  * 
79  * 31    7/24/98 11:14a Allender
80  * start of new command line options for version 1.04
81  * 
82  * 30    5/21/98 1:50a Dave
83  * Remove obsolete command line functions. Reduce shield explosion packets
84  * drastically. Tweak PXO screen even more. Fix file xfer system so that
85  * we can guarantee file uniqueness.
86  * 
87  * 29    5/18/98 9:10p Dave
88  * Put in many new PXO features. Fixed skill level bashing in multiplayer.
89  * Removed several old command line options. Put in network config files.
90  * 
91  * 28    5/09/98 7:16p Dave
92  * Put in CD checking. Put in standalone host password. Made pilot into
93  * popup scrollable.
94  * 
95  * 27    4/23/98 8:27p Allender
96  * basic support for cutscene playback.  Into movie code in place.  Tech
97  * room can view cutscenes stored in CDROM_dir variable
98  * 
99  * 26    4/09/98 5:43p Dave
100  * Remove all command line processing from the demo. Began work fixing up
101  * the new multi host options screen.
102  * 
103  * 25    4/02/98 11:40a Lawrance
104  * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
105  * 
106  * 24    4/01/98 5:56p Dave
107  * Fixed a messaging bug which caused msg_all mode in multiplayer not to
108  * work. Compile out a host of multiplayer options not available in the
109  * demo.
110  * 
111  * 23    3/14/98 2:48p Dave
112  * Cleaned up observer joining code. Put in support for file xfers to
113  * ingame joiners (observers or not). Revamped and reinstalled pseudo
114  * lag/loss system.
115  * 
116  * 22    2/22/98 12:19p John
117  * Externalized some strings
118  * 
119  * 21    1/31/98 4:32p Dave
120  * Put in new support for VMT player validation, game logging in and game
121  * logging out.
122  * 
123  * 20    12/10/97 4:45p Dave
124  * Added in more detailed support for multiplayer packet lag/loss. Fixed
125  * some multiplayer stuff. Added some controls to the standalone.
126  * 
127  * 19    12/09/97 6:14p Lawrance
128  * add -nomusic flag
129  * 
130  * 18    12/01/97 5:10p Dave
131  * Fixed a syntax bug.
132  * 
133  * 17    12/01/97 4:59p Dave
134  * Synchronized multiplayer debris objects. Put in pilot popup in main
135  * hall. Optimized simulated multiplayer lag module. Fixed a potential
136  * file_xfer bug.
137  * 
138  * 16    11/28/97 7:04p Dave
139  * Emergency checkin due to big system crash.
140  * 
141  * 15    11/28/97 5:06p Dave
142  * Put in facilities for simulating multiplayer lag.
143  * 
144  * 14    11/24/97 5:42p Dave
145  * Fixed a file xfer buffer free/malloc problem. Lengthened command line
146  * switch string parse length.
147  * 
148  * 13    11/12/97 4:39p Dave
149  * Put in multiplayer campaign support parsing, loading and saving. Made
150  * command-line variables better named. Changed some things on the initial
151  * pilot select screen.
152  * 
153  * 12    11/11/97 4:54p Dave
154  * Put in support for single vs. multiplayer pilots. Put in initial player
155  * selection screen (no command line option yet). Started work on
156  * multiplayer campaign file save gaming.
157  * 
158  * 11    11/11/97 11:55a Allender
159  * initialize network at beginning of application.  create new call to set
160  * which network protocol to use
161  * 
162  * 10    9/18/97 10:12p Dave
163  * Added -gimmemedals, which gives the current pilot all the medals in the
164  * game (debug)
165  * 
166  * 9     9/18/97 9:20a Dave
167  * Minor modifications
168  * 
169  * 8     9/15/97 11:40p Lawrance
170  * remove demo granularity switch
171  * 
172  * 7     9/09/97 3:39p Sandeep
173  * warning level 4 bugs
174  * 
175  * 6     9/03/97 5:03p Lawrance
176  * add support for -nosound command line parm
177  * 
178  * 5     8/22/97 8:52a Dave
179  * Removed a return statement which would have broken the parser out too
180  * early.
181  * 
182  * 4     8/21/97 4:55p Dave
183  * Added a switch for multiplayer chat streaming. Added a section for
184  * global command line vars.
185  * 
186  * 3     8/06/97 2:26p Dave
187  * Made the command line parse more robust. Made it easier to add and
188  * process new command-line switches.
189  * 
190  * 2     8/04/97 3:13p Dave
191  * Added command line functions. See cmdline.cpp for directions on adding
192  * new switches
193  * 
194  * 1     8/04/97 9:58a Dave
195  * 
196  * $NoKeywords: $
197  */
198
199 #include <string.h>
200 #include <stdlib.h>
201 #include "cmdline.h"
202 #include "linklist.h"
203 #include "systemvars.h"
204 #include "multi.h"
205 #include "cfile.h"
206
207 // variables
208 class cmdline_parm {
209 public:
210         cmdline_parm *next, *prev;
211         char *name;                                             // name of parameter, must start with '-' char
212         char *help;                                             // help text for this parameter
213         char *args;                                             // string value for parameter arguements (NULL if no arguements)
214         int name_found;                         // true if parameter on command line, otherwise false
215
216         cmdline_parm(char *name, char *help);
217         ~cmdline_parm();
218         int found();
219         int get_int();
220         float get_float();
221         char *str();
222 };
223
224 // here are the command line parameters that we will be using for FreeSpace
225 cmdline_parm standalone_arg("-standalone", NULL);
226 cmdline_parm nosound_arg("-nosound", NULL);
227 cmdline_parm nomusic_arg("-nomusic", NULL);
228 cmdline_parm startgame_arg("-startgame", NULL);
229 cmdline_parm gamename_arg("-gamename", NULL);
230 cmdline_parm gamepassword_arg("-password", NULL);
231 cmdline_parm gameclosed_arg("-closed", NULL);
232 cmdline_parm gamerestricted_arg("-restricted", NULL);
233 cmdline_parm allowabove_arg("-allowabove", NULL);
234 cmdline_parm allowbelow_arg("-allowbelow", NULL);
235 cmdline_parm port_arg("-port", NULL);
236 cmdline_parm connect_arg("-connect", NULL);
237 cmdline_parm multilog_arg("-multilog", NULL);
238 cmdline_parm server_firing_arg("-oldfire", NULL);
239 cmdline_parm client_dodamage("-clientdamage", NULL);
240 cmdline_parm pof_spew("-pofspew", NULL);
241 cmdline_parm d3d_32bit("-32bit", NULL);
242 cmdline_parm mouse_coords("-coords", NULL);
243 cmdline_parm timeout("-timeout", NULL);
244 cmdline_parm d3d_window("-window", NULL);
245
246 int Cmdline_multi_stream_chat_to_file = 0;
247 int Cmdline_freespace_no_sound = 0;
248 int Cmdline_freespace_no_music = 0;
249 int Cmdline_gimme_all_medals = 0;
250 int Cmdline_use_last_pilot = 0;
251 int Cmdline_multi_protocol = -1;
252 int Cmdline_cd_check = 1;
253 int Cmdline_start_netgame = 0;
254 int Cmdline_closed_game = 0;
255 int Cmdline_restricted_game = 0;
256 int Cmdline_network_port = -1;
257 char *Cmdline_game_name = NULL;
258 char *Cmdline_game_password = NULL;
259 char *Cmdline_rank_above= NULL;
260 char *Cmdline_rank_below = NULL;
261 char *Cmdline_connect_addr = NULL;
262 int Cmdline_multi_log = 0;
263 int Cmdline_server_firing = 0;
264 int Cmdline_client_dodamage = 0;
265 int Cmdline_spew_pof_info = 0;
266 int Cmdline_force_32bit = 0;
267 int Cmdline_mouse_coords = 0;
268 int Cmdline_timeout = -1;
269
270 int Cmdline_window = 0;
271
272 static cmdline_parm Parm_list(NULL, NULL);
273 static int Parm_list_inited = 0;
274
275
276 //      Return true if this character is an extra char (white space and quotes)
277 int is_extra_space(char ch)
278 {
279         return ((ch == ' ') || (ch == '\t') || (ch == 0x0a) || (ch == '\'') || (ch == '\"'));
280 }
281
282
283 // eliminates all leading and trailing extra chars from a string.  Returns pointer passed in.
284 char *drop_extra_chars(char *str)
285 {
286         int s, e;
287
288         s = 0;
289         while (str[s] && is_extra_space(str[s]))
290                 s++;
291
292         e = strlen(str) - 1;
293         while (e > s) {
294                 if (!is_extra_space(str[e])){
295                         break;
296                 }
297
298                 e--;
299         }
300
301         if (e > s){
302                 memmove(str, str + s, e - s + 1);
303         }
304
305         str[e - s + 1] = 0;
306         return str;
307 }
308
309
310 // internal function - copy the value for a parameter agruement into the cmdline_parm arg field
311 void parm_stuff_args(cmdline_parm *parm, char *cmdline)
312 {
313         char buffer[1024];
314         memset(buffer, 0, 1024);
315         char *dest = buffer;
316
317         cmdline += strlen(parm->name);
318
319         while ((*cmdline != 0) && (*cmdline != '-')) {
320                 *dest++ = *cmdline++;
321         }
322
323         drop_extra_chars(buffer);
324
325         // mwa 9/14/98 -- made it so that newer command line arguments found will overwrite
326         // the old arguments
327 //      Assert(parm->args == NULL);
328         if ( parm->args != NULL ) {
329                 delete( parm->args );
330                 parm->args = NULL;
331         }
332
333         int size = strlen(buffer) + 1;
334         if (size > 0) {
335                 parm->args = new char[size];
336                 memset(parm->args, 0, size);
337                 strcpy(parm->args, buffer);
338         }
339 }
340
341
342 // internal function - parse the command line, extracting parameter arguements if they exist
343 // cmdline - command line string passed to the application
344 void os_parse_parms(char *cmdline)
345 {
346         // locate command line parameters
347         cmdline_parm *parmp;
348         char *cmdline_offset;
349
350         for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
351                 cmdline_offset = strstr(cmdline, parmp->name);
352                 if (cmdline_offset) {
353                         parmp->name_found = 1;
354                         parm_stuff_args(parmp, cmdline_offset);
355                 }
356         }
357 }
358
359
360 // validate the command line parameters.  Display an error if an unrecognized parameter is located.
361 void os_validate_parms(char *cmdline)
362 {
363         cmdline_parm *parmp;
364         char seps[] = " ,\t\n";
365         char *token;
366         int parm_found;
367
368    token = strtok(cmdline, seps);
369    while(token != NULL) {
370         
371                 if (token[0] == '-') {
372                         parm_found = 0;
373                         for (parmp = GET_FIRST(&Parm_list); parmp !=END_OF_LIST(&Parm_list); parmp = GET_NEXT(parmp) ) {
374                                 if (!stricmp(parmp->name, token)) {
375                                         parm_found = 1;
376                                         break;
377                                 }
378                         }
379
380                         if (parm_found == 0) {
381                                 Error(LOCATION,"Unrecogzined command line parameter %s", token);
382                         }
383                 }
384
385                 token = strtok(NULL, seps);
386         }
387 }
388
389
390 // Call once to initialize the command line system
391 //
392 // cmdline - command line string passed to the application
393 void os_init_cmdline(char *cmdline)
394 {
395         FILE *fp;
396
397         // read the cmdline.cfg file from the data folder, and pass the command line arguments to
398         // the the parse_parms and validate_parms line.  Read these first so anything actually on
399         // the command line will take precedence
400 #ifdef PLAT_UNIX
401         fp = fopen("Data/cmdline.cfg", "rt");
402 #else
403         fp = fopen("data\\cmdline.cfg", "rt");
404 #endif
405
406         // if the file exists, get a single line, and deal with it
407         if ( fp ) {
408                 char buf[1024], *p;
409
410                 fgets(buf, 1024, fp);
411
412                 // replace the newline character with a NUL:
413                 if ( (p = strrchr(buf, '\n')) != NULL ) {
414                         *p = '\0';
415                 }
416
417                 os_parse_parms(buf);
418                 os_validate_parms(buf);
419                 fclose(fp);
420         }
421
422
423
424         os_parse_parms(cmdline);
425         os_validate_parms(cmdline);
426
427 }
428
429
430 // arg constructor
431 // name_ - name of the parameter, must start with '-' character
432 // help_ - help text for this parameter
433 cmdline_parm::cmdline_parm(char *name_, char *help_)
434 {
435         name = name_;
436         help = help_;
437         args = NULL;
438         name_found = 0;
439
440         if (Parm_list_inited == 0) {
441                 list_init(&Parm_list);
442                 Parm_list_inited = 1;
443         }
444
445         if (name != NULL) {
446                 list_append(&Parm_list, this);
447         }
448 }
449
450
451 // destructor - frees any allocated memory
452 cmdline_parm::~cmdline_parm()
453 {
454         if (args) {
455                 delete [] args;
456                 args = NULL;
457         }
458 }
459
460
461 // returns - true if the parameter exists on the command line, otherwise false
462 int cmdline_parm::found()
463 {
464         return name_found;
465 }
466
467
468 // returns - the interger representation for the parameter arguement
469 int cmdline_parm::get_int()
470 {
471         Assert(args);
472         return atoi(args);
473 }
474
475
476 // returns - the float representation for the parameter arguement
477 float cmdline_parm::get_float()
478 {
479         Assert(args);
480         return (float)atof(args);
481 }
482
483
484 // returns - the string value for the parameter arguement
485 char *cmdline_parm::str()
486 {
487         Assert(args);
488         return args;
489 }
490
491 // external entry point into this modules
492 int parse_cmdline(char *cmdline)
493 {
494         os_init_cmdline(cmdline);
495
496         // is this a standalone server??
497         if (standalone_arg.found()) {
498                 Is_standalone = 1;
499         }
500
501         // run with no sound
502         if ( nosound_arg.found() ) {
503                 Cmdline_freespace_no_sound = 1;
504         }
505
506         // run with no music
507         if ( nomusic_arg.found() ) {
508                 Cmdline_freespace_no_music = 1;
509         }
510
511         // should we start a network game
512         if ( startgame_arg.found() ) {
513                 Cmdline_use_last_pilot = 1;
514                 Cmdline_start_netgame = 1;
515         }
516
517         // closed network game
518         if ( gameclosed_arg.found() ) {
519                 Cmdline_closed_game = 1;
520         }
521
522         // restircted network game
523         if ( gamerestricted_arg.found() ) {
524                 Cmdline_restricted_game = 1;
525         }
526
527         // get the name of the network game
528         if ( gamename_arg.found() ) {
529                 Cmdline_game_name = gamename_arg.str();
530
531                 // be sure that this string fits in our limits
532                 if ( strlen(Cmdline_game_name) > MAX_GAMENAME_LEN ) {
533                         Cmdline_game_name[MAX_GAMENAME_LEN-1] = '\0';
534                 }
535         }
536
537         // get the password for a pssword game
538         if ( gamepassword_arg.found() ) {
539                 Cmdline_game_password = gamepassword_arg.str();
540
541                 // be sure that this string fits in our limits
542                 if ( strlen(Cmdline_game_name) > MAX_PASSWD_LEN ) {
543                         Cmdline_game_name[MAX_PASSWD_LEN-1] = '\0';
544                 }
545         }
546
547         // set the rank above/below arguments
548         if ( allowabove_arg.found() ) {
549                 Cmdline_rank_above = allowabove_arg.str();
550         }
551         if ( allowbelow_arg.found() ) {
552                 Cmdline_rank_below = allowbelow_arg.str();
553         }
554
555         // get the port number for games
556         if ( port_arg.found() ) {
557                 Cmdline_network_port = port_arg.get_int();
558         }
559
560         // the connect argument specifies to join a game at this particular address
561         if ( connect_arg.found() ) {
562                 Cmdline_use_last_pilot = 1;
563                 Cmdline_connect_addr = connect_arg.str();
564         }
565
566         // see if the multilog flag was set
567         if ( multilog_arg.found() ){
568                 Cmdline_multi_log = 1;
569         }       
570
571         // maybe use old-school server-side firing
572         if (server_firing_arg.found() ){
573                 Cmdline_server_firing = 1;
574         }
575
576         // maybe use old-school client damage
577         if(client_dodamage.found()){
578                 Cmdline_client_dodamage = 1;
579         }       
580
581         // spew pof info
582         if(pof_spew.found()){
583                 Cmdline_spew_pof_info = 1;
584         }
585
586         // 32 bit
587         if(d3d_32bit.found()){
588                 Cmdline_force_32bit = 1;
589         }
590
591         // mouse coords
592         if(mouse_coords.found()){
593                 Cmdline_mouse_coords = 1;
594         }
595
596         // net timeout
597         if(timeout.found()){
598                 Cmdline_timeout = timeout.get_int();
599         }
600
601         // d3d windowed
602         if(d3d_window.found()){
603                 Cmdline_window = 1;
604         }
605
606         return 1;
607 }
608