diff --git a/source/src/server.cpp b/source/src/server.cpp index ccd5e596..ceb0b4bd 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -3519,9 +3519,7 @@ int main(int argc, char **argv) { case '-': if(!strncmp(argv[i], "--wizard", 8)) - { - return wizardmain(argc-1, argv+1); - } + return wizardmain(argc, argv); break; case 'S': service = a; break; default: printf("WARNING: unknown commandline option\n"); diff --git a/source/src/tools.h b/source/src/tools.h index 63d66d5a..ceaeedf9 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -470,6 +470,15 @@ template struct vector buf[i] = e; return buf[i]; } + + T *insert(int i, const T *e, int n) + { + if(ulen+n>alen) growbuf(ulen+n); + loopj(n) add(T()); + for(int p = ulen-1; p>=i+n; p--) buf[p] = buf[p-n]; + loopj(n) buf[i+j] = e[j]; + return &buf[i]; + } }; static inline uint hthash(const char *key) diff --git a/source/src/wizard.cpp b/source/src/wizard.cpp index 1235ab2d..e8748f30 100644 --- a/source/src/wizard.cpp +++ b/source/src/wizard.cpp @@ -1,13 +1,6 @@ // wizard to start an AssaultCube server and storing the configuration -#include "platform.h" - -#include -#include -#include -#include - -using namespace std; +#include "cube.h" #ifdef WIN32 #ifndef __GNUC__ @@ -20,155 +13,164 @@ using namespace std; #include #endif +static void addarg(vector &argstr, const char *name) +{ + argstr.add(' '); + argstr.put(name, strlen(name)); +} + +static void addarg(vector &argstr, const char *name, const char *val) +{ + addarg(argstr, name); + bool space = strchr(val, ' ')!=NULL; + if(space) argstr.add('"'); + argstr.put(val, strlen(val)); + if(space) argstr.add('"'); +} + +static void readarg(const char *desc, char *val, int len) +{ + printf("%s: ", desc); + fflush(stdout); + fgets(val, len, stdin); + char *end = strchr(val, '\n'); + if(end) *end = '\0'; +} + +static void readarg(vector &argstr, const char *desc, const char *name) +{ + string val = ""; + readarg(desc, val, sizeof(val)); + if(val[0]) addarg(argstr, name, val); +} + int wizardmain(int argc, char **argv) { - if(argc < 3) + const char *outfile = NULL, *relpath = NULL; + for(int i = 1; i < argc; i++) { - cout << "invalid arguments specified!" << endl << "usage: ac_server " << endl; + if(!strncmp(argv[i], "--wizard", 8)) continue; + if(!outfile) outfile = argv[i]; + else if(!relpath) relpath = argv[i]; + } + if(!outfile || !relpath) + { + printf("invalid arguments specified!\n"); + printf("usage: ac_server \n"); return EXIT_FAILURE; } - /* You will never now what server.sh script will really place before --wizard */ - int k, i = 0; - while ( ( k = strncmp(argv[i],"--wizard",8) ) != 0 && i < 20 ) i++; - if ( k != 0 ) return EXIT_FAILURE; - - string outfile(argv[++i]); - string relpath(argv[++i]); - - map args; - - cout << "AssaultCube Server Wizard" << endl << endl; - cout << "You can now specify some optional server settings. " - "The default settings will be used if you decide to leave the fields empty. " - "If you're not sure: leave the field empty. " - "See README.html for a description of the settings." << endl << endl; - - cout << "server description:\t"; - getline(cin, args["n"]); - - cout << "message of the day:\t"; - getline(cin, args["o"]); - - cout << "max clients:\t\t"; - getline(cin, args["c"]); - - cout << "admin password:\t\t"; - getline(cin, args["x"]); - - cout << "player password:\t\t"; - getline(cin, args["p"]); - - cout << "server port:\t\t"; - getline(cin, args["f"]); - - string ispub; - cout << "public server (Yes|no):\t"; - getline(cin, ispub); - - string cmds; - cout << "additional commandline parameters:\t"; - getline(cin, cmds); + printf("AssaultCube Server Wizard\n\n"); + printf("You can now specify some optional server settings.\n" + "The default settings will be used if you decide to leave the fields empty.\n" + "If you're not sure: leave the field empty.\n" + "See README.html for a description of the settings.\n\n"); + vector argstr; + readarg(argstr, "server description", "-n"); + readarg(argstr, "message of the day", "-o"); + readarg(argstr, "max clients", "-c"); + readarg(argstr, "admin password", "-x"); + readarg(argstr, "player password", "-p"); + readarg(argstr, "server port", "-f"); + string ispub = ""; + readarg("public server (Yes|no)", ispub, sizeof(ispub)); + if(toupper(ispub[0]) == 'N') addarg(argstr, "-m"); + string cmds = ""; + readarg("additional command-line parameters", cmds, sizeof(cmds)); + if(cmds[0]) addarg(argstr, cmds); #ifdef WIN32 - string wsname, wsdisplayname; - cout << "win service name:\t"; - getline(cin, wsname); + string wsname = "", wsdisplayname = ""; + readarg("win service name", wsname, sizeof(wsname)); + if(wsname[0]) + readarg("win service display", wsdisplayname, sizeof(wsdisplayname)); - if(!wsname.empty()) +#endif + + printf("\nWriting your configuration to %s ... ", outfile); fflush(stdout); + + argstr.add('\0'); + + FILE *script = fopen(outfile, "w"); + if(!script) { - cout << "win service display:\t"; - getline(cin, wsdisplayname); + printf("Failed!\n"); + return EXIT_FAILURE; } -#endif - - string argstr; - - for(map::iterator i = args.begin(); i != args.end(); i++) - { - if((*i).second.empty()) continue; // arg value not set - else - { - argstr += " -" + (*i).first; - if((*i).second.find(" ") == string::npos) argstr += (*i).second; - else argstr += '"' + (*i).second + '"'; // escape spaces - } - } - if(toupper(*(ispub.c_str())) == 'N') argstr += " -mlocalhost"; - if(!cmds.empty()) argstr += " " + cmds; - - cout << endl << "Writing your configuration to " << outfile << " ... "; - - try - { - fstream startupScript(outfile.c_str(), ios::out); #ifdef WIN32 - startupScript << relpath << argstr << endl << "pause" << endl; + fprintf(script, "%s%s\npause\n", relpath, argstr.getbuf()); #elif __GNUC__ - startupScript << "#! /bin/sh" << endl << relpath << argstr << endl; + fprintf(script, "#!/bin/sh\n%s%s\n", relpath, argstr.getbuf()); #endif - startupScript.close(); - } - catch(...) - { - cout << "Failed!" << endl; - return EXIT_FAILURE; - } + fclose(script); - cout << "Done" << endl << endl; - cout << "Note: You can start " << outfile << " directly the next time you want to use this configuration again." << endl << endl; + printf("Done\n\n"); + printf("Note: You can start %s directly the next time you want to use this configuration again.\n\n", outfile); #ifdef WIN32 - if(!wsname.empty()) + if(wsname[0]) { - if(wsdisplayname.empty()) wsdisplayname = wsname; + if(!wsdisplayname[0]) copystring(wsdisplayname, wsname); - cout << "Installing the AC Server as windows service ... "; + printf("Installing the AC Server as windows service ... "); fflush(stdout); - char path[MAX_PATH]; - _getcwd(path, MAX_PATH); - strncat(path, ("\\" + relpath + " -S" + wsname + " " + argstr).c_str(), MAX_PATH); + vector path; + databuf cwd = path.reserve(MAX_PATH); + if(!_getcwd(cwd.buf, MAX_PATH)) + { + printf("Failed!\n"); + printf("Could not get current working directory: %d\n", GetLastError()); + return EXIT_FAILURE; + } + path.advance(strlen(cwd.buf)); + path.add('\\'); + path.put(relpath, strlen(relpath)); + path.put(" -S", 3); + path.put(wsname, strlen(wsname)); + path.add(' '); + path.put(argstr, argstr.length()); - winserviceinstaller installer(wsname.c_str(), wsdisplayname.c_str(), path); + winserviceinstaller installer(wsname, wsdisplayname, path.getbuf()); int r; if(!installer.OpenManger()) { - cout << "Failed!" << endl; - cout << "Could not open the Service Control Manager: " << GetLastError() << endl; + printf("Failed!\n"); + printf("Could not open the Service Control Manager: %d\n", GetLastError()); installer.CloseManager(); return EXIT_FAILURE; } if((r = installer.IsInstalled()) != 0) { - cout << "Failed!" << endl; - if(r == -1) cout << "Error accessing the Service Control Manager" << endl; - else if(r == 1) cout << "A windows service with this name (" << wsname << ")is already installed: " << GetLastError() << endl; + printf("Failed!\n"); + if(r == -1) printf("Error accessing the Service Control Manager\n"); + else if(r == 1) printf("A windows service with this name (%s) is already installed: %d\n", wsname, GetLastError()); return EXIT_FAILURE; } if((r = installer.Install()) != 1) { - cout << "Failed!" << endl; - if(r == -1) cout << "Error accessing the Service Control Manager" << endl; - else if(r == 0) cout << "Could not create the new windows service: " << GetLastError() << endl; + printf("Failed!\n"); + if(r == -1) printf("Error accessing the Service Control Manager\n"); + else if(r == 0) printf("Could not create the new windows service: %d\n", GetLastError()); return EXIT_FAILURE; } - cout << "Done" << endl << endl; - cout << "Note: You can now manage your AC server using services.msc and sc.exe" << endl << endl; + printf("Done\n\n"); + printf("Note: You can now manage your AC server using services.msc and sc.exe\n\n"); } #endif - cout << "Press Enter to start the server now" << endl; - cin.get(); - cout << "Starting the AC server ..." << endl; - system((relpath + argstr).c_str()); + printf("Press Enter to start the server now\n"); + fgetc(stdin); + printf("Starting the AC server ...\n"); + argstr.insert(0, relpath, strlen(relpath)); + system(argstr.getbuf()); return EXIT_SUCCESS; }