// p4dcfg // main program // // $Author: sknop $ // $DateTime: 2008/04/11 06:00:06 $ // $Revision: #16 $ #include <iostream> #include <cstdlib> #include <cstring> #include <string> #include <getopt.h> #include "configuration.h" #include "configparser.h" #include "stringtools.h" const char * defaultConfigFile = "/etc/p4dcfg.conf"; class P4DCfg { private: std::string _procname; std::string _configFile; std::string _command; std::string _server; std::string _type; bool _verbose; Configuration _configuration; int usage(int retval) { std::cout << "Usage : \n" << std::endl; std::cout << "\t" << _procname << " [options] <command> <name>" << std::endl; std::cout << "\t" << _procname << " -h" << std::endl; std::cout << "\n\tOptions:\n" << std::endl; std::cout << "\t\t-v\t\t\t\tverbose output" << std::endl; std::cout << "\t\t-c <configfile>\t\t\tConfig file used (only root, default /etc/p4dcfg.conf)" << std::endl; std::cout << "\t\t-t {p4d, p4p, p4web, p4ftp}\tRestrict to process type" << std::endl; std::cout << "\t\t-z\t\t\t\tcompress checkpoints" << std::endl; std::cout << "\t\t-h\t\t\t\tprint this message" << std::endl; std::cout << "\n\tCommands:\n" << std::endl; std::cout << "\t\tstart\t\tstarts the server(s)" << std::endl; std::cout << "\t\tstop\t\tstops the server(s)" << std::endl; std::cout << "\t\trestart\t\trestarts the server(s)" << std::endl; std::cout << "\t\tstatus\t\tindicates the state of the server(s)" << std::endl; std::cout << "\t\tcheckpoint\tperforms a checkpoint on the server(s) - only p4d" << std::endl; std::cout << "\t\tjournal\t\trotates the journal of the server(s) - only p4d" << std::endl; std::cout << "\n\tIf <name> is -a, all named services are affected" << std::endl; std::cout << std::endl; return retval; } int version() { std::cout << "p4dcfg 1.0.3" << std::endl << std::endl; std::cout << "Copyright (c) 2007, Perforce Software, Inc. All rights reserved." << std::endl; return 0; } public: P4DCfg() : _configFile(defaultConfigFile), _type(""), _verbose(false) { } int execute(int argc, const char *argv[]) { _procname = argv[0]; try { int retval = parseCommandLine(argc, argv); // safety : this is a setuid process // if we are not root originally, ensure we cannot do // too much damage setSafeEuid(); retval = !retval && parseConfigFile(); retval = !retval && executeServerCommand(); return 0; } catch(ParseException& e) { std::cout << e.what() << " line # " << e.lineNumber() << std::endl; return 1; } catch(ConfigException& e) { std::cout << e.what() << std::endl; return 1; } } private: int parseConfigFile() { ConfigParser parser(_configFile, &_configuration); parser.parse(); return 0; } int executeServerCommand() { if (_command == "stop" || _command == "restart") { _configuration.reverseServerOrder(); } int result = 0; if (_server != "-a") { if (_type == "") { _configuration.execIfName(_command, _server); } else { _configuration.execIfTypeAndName(_command, _type, _server); } } else { if (_type == "") { _configuration.execAll(_command); } else { _configuration.execIfType(_command, _type); } } if (result == -1) { // child exiting, this is ok result = 0; } return result; } // parse arguments // read config file // parse config file // determine which server (or all) to access // execute command on that server int parseCommandLine(int argc, const char *argv[]) { int c; while (1) { static const char * options = "hVvc:t:az"; #ifdef _GNU_SOURCE int optionIndex = 0; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"verbose", 0, 0, 'v'}, {"config", 1, 0, 'c'}, {"type", 1, 0, 't'}, {"all", 0, 0, 'a'}, {"compress", 0, 0, 'z'}, {0, 0, 0, 0} }; c = getopt_long (argc, (char **) argv, options, long_options, &optionIndex); #else c = getopt(argc, (char **) argv, options); #endif if (c == -1) break; switch (c) { case 'v': _verbose = true; _configuration.setVerbose(_verbose); break; case 'c': if (getuid() == 0) { _configFile = optarg; } else { std::cerr << "Only root is allowed to specify config file" << std::endl; } break; case 't': _type = optarg; break; case 'a': _server = "-a"; break; case 'z': _configuration.setCompressCheckpoint(true); break; case 'V': return version(); case 'h': default: return usage(-1); } } if (optind < argc) { _command = argv[optind]; optind++; } else { return usage(1); } if (_server != "-a") { if (optind < argc) { _server = argv[optind]; optind++; } else { return usage(1); } } return 0; } }; int main(int argc, const char *argv[]) { P4DCfg cfg; return cfg.execute(argc, argv); }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 6307 | Sven Erik Knop |
Several updates. Each command now accepts an "Options" variable for miscellaneous parameters for the executables that have no equivalent environment variable. For example, p4web has the option -b or -B, which can only be invoked on the command line. Updated documentation as well. |
||
#2 | 5987 | Sven Erik Knop |
Few minor changes: All commands now accept variable called "Options". This can be used to collect all options for which Perforce has not defined an environment variable - for example the undocumented "-C1" for p4d to start a case insensitive server. p4d also accepts the variables P4USER and P4PASSWD. These are only used for stopping the service, which is done first via "p4 admin stop". Note that if the stop via the admin command fails, p4dcfg will stop the service via a kill |
||
#1 | 5882 | Sven Erik Knop | initial publish |