/* eurephiadm.c -- CLI based admin program for eurephia * * GPLv2 only - Copyright (C) 2008, 2009 * David Sommerseth * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; version 2 * of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #define MODULE "eurephiadm" #include "argparser.h" #include "client_context.h" #include "client_config.h" #include "client_session.h" #include "get_console_input.h" #include "commands.h" char *print_version(char *fprg) { char *prg = basename(fprg); fprintf(stdout, "%s (v%s) - eurephia administration utility\n" "Copyright (C) 2008 David Sommerseth \n", prg, EUREPHIAVERSION); return prg; } void help_Help() { char *argv[] = { MODULE, NULL }; cmd_Help(NULL, NULL, NULL, 1, argv); } int cmd_Help(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { eurephiadm_functions *func = NULL; int i; char *prg = NULL; // Print the modules help screen if module name is given if( ((argc == 2) && (strcmp(argv[0], "help") == 0)) || ((argc == 3) && (*argv[1] == '-')) ) { char *help = (argc == 2 ? argv[1] : argv[2]); for( i = 0; cmdline_functions[i].command != NULL; i++ ) { func = (eurephiadm_functions *)&cmdline_functions[i]; if( (strcmp(func->command, help) == 0) && (func->helpfunc != NULL) ) { func->helpfunc(); return 0; } } fprintf(stderr, "%s: ERROR :: Could not find help for module '%s'\n", MODULE , help); return 1; } prg = print_version((strcmp(argv[0], "help") == 0) ? MODULE : argv[0]); fprintf(stdout, "\n Usage: %s [global options] [command options]\n\n", prg); fprintf(stdout," %-20.20s %-20.20s %-30.30s\n", "-V | --version", "", "Print version of eurephiadm"); fprintf(stdout," %-20.20s %-20.20s %-30.30s\n", "-l | --log", "", "Log to file"); fprintf(stdout," %-20.20s %-20.20s %-30.30s\n", "-L | --log-level", "", "Set log verbosity"); fprintf(stdout,"\n %-20.20s %-20.20s %-30.30s\n", "Command","Arguments","Description"); fprintf(stdout, " ------------------------------------------------------------------------\n"); for( i = 0; cmdline_functions[i].command != NULL; i++ ) { func = (eurephiadm_functions *)&cmdline_functions[i]; fprintf(stdout," %-20.20s %-20.20s %-30.30s\n", func->command, (func->arghint != NULL ? func->arghint : ""), func->helpinfo); } fprintf(stdout, "\n"); return 0; } int cmd_Logout(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { int rc = 0; rc = eDBadminLogout(ctx, argv[0]); fprintf(stdout, "%s\n", (rc == 1 ? "Logged out succesfully" : "Logout failed.")); return (rc == 0); } int cmd_ShowCfg(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { void dump_values(eurephiaVALUES *vls) { eurephiaVALUES *ptr = NULL; fprintf(stdout, "----------------------------------------------------------------------\n"); for( ptr = vls; ptr != NULL; ptr = ptr->next) { if( ptr->key != NULL ) { fprintf(stdout, "%20s = %s\n", ptr->key, ptr->val); } } fprintf(stdout, "----------------------------------------------------------------------\n"); } if( cfg != NULL ) { fprintf(stdout, "\n** eurephiadm configuration settings (config file) **\n"); dump_values(cfg); fprintf(stdout, "\n"); } if( ctx != NULL ) { fprintf(stdout, "** eurephia configuration settings (set in database) **\n"); dump_values(ctx->dbc->config); fprintf(stdout, "\n"); } return 0; } int eurephia_ConnectDB(eurephiaCTX *ctx, const char *argstr) { char *delims = " "; char *cp = NULL; const char *dbargv[MAX_ARGUMENTS]; int dbargc = 0; if( (argstr == NULL) || (strlen(argstr) < 1) ) { eurephia_log(ctx, LOG_FATAL, 0, "No database connection string given"); return 0; } // Split up argstr into separate arguments cp = strdup(argstr); assert(cp != NULL); dbargc = 0; dbargv[dbargc] = strtok(cp, delims); while( (dbargv[dbargc] != NULL) && (dbargc <= MAX_ARGUMENTS) ) { dbargv[++dbargc] = strtok(NULL, delims); } if( !eDBconnect(ctx, dbargc, dbargv) ) { eurephia_log(ctx, LOG_PANIC, 0, "Could not connect to the database"); eDBlink_close(ctx); return 0; } free_nullsafe(cp); return 1; } eurephiaSESSION *do_login(eurephiaCTX *ctx, eurephiaVALUES *cfg, const char *req_access) { eurephiaSESSION *session = NULL; char username[33], password[33], *tmp = NULL; int uid = 0; memset(&username, 0, 33); memset(&password, 0, 33); if( (tmp = eGet_value(cfg, "username")) == NULL ) { memset(username, 0, 34); get_console_input(username, 32, "User:", 0); } else { strncpy(username, tmp, 32); } get_console_input(password, 32, "Password:", 1); if( (uid = eDBadminAuth(ctx, req_access, username, password)) < 1 ) { // Register failure memset(username, 0, 33); memset(password, 0, 33); return NULL; } memset(username, 0, 33); memset(password, 0, 33); session = create_session(ctx, NULL); snprintf(username, 30, "%i", uid); // Borrow username for converting uid to a string if( !eDBset_session_value(ctx, session, "uid", username) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not update session variables (uid)"); eDBfree_session(ctx, session); return NULL; }; if( !eDBadminRegisterLogin(ctx, session) ) { eurephia_log(ctx, LOG_FATAL, 0, "Could not register login"); eDBfree_session(ctx, session); return NULL; } return session; } char *args2string(int argc, char **argv) { char *res = NULL; int len = 0, i = 0; for( i = 0; i < argc; i++ ) { len += strlen_nullsafe(argv[i]) + 1; } res = (char *) malloc(len+2); memset(res, 0, len+2); for( i = 0; i < argc; i++ ) { strcat(res, argv[i]); strcat(res, " "); } return res; } int main(int argc, char **argv) { FILE *logfile = NULL; int loglevel = 0; eurephiaCTX *ctx = NULL; eurephiaSESSION *session = NULL; eurephiaVALUES *cfg = NULL; char *sesskey_file = NULL; char *dbparams = NULL, *cmdargv[MAX_ARGUMENTS]; int rc = 0, i = 0, found = 0, cmdargc = 0, argi = 0; eurephiadm_functions *call_fnc; // Global arguments we accept static e_options argopts[] = { {"--version", "-V", 0}, {"--help", "-h", 0}, {"--log", "-l", 1}, {"--log-level", "-L", 1}, {NULL, NULL, 0} }; if( argc < 2 ) { cmd_Help(NULL, NULL, NULL, argc, argv); return 1; } // Parse argument line argi = 1; for( argi = 1; argi < argc; argi++ ) { if( *argv[argi] != '-' ) { break; } switch( eurephia_getopt(&argi, argc, argv, argopts) ) { case 'V': print_version(argv[0]); return 0; case 'h': cmd_Help(NULL, NULL, NULL, argc, argv); return 0; case 'l': if( (logfile = fopen(optargs[0], "wb")) == NULL ) { fprintf(stderr, "%s: ERROR :: Could not open log file: %s\n", basename(argv[0]), optargs[0]); return 0; } break; case 'L': loglevel = atoi_nullsafe(optargs[0]); break; default: return 1; break; } } if( argi >= argc ) { fprintf(stderr, "%s: ERROR :: No command given\n", basename(argv[0])); return 1; } else { for( i = argi; ((i < argc) && (i < MAX_ARGUMENTS)); i++ ) { cmdargv[cmdargc++] = argv[i]; } } // Find the command requested and save a pointer to that command's C function for( i = 0; cmdline_functions[i].command != NULL; i++ ) { call_fnc = (eurephiadm_functions *)&cmdline_functions[i]; if( strcmp(call_fnc->command, cmdargv[0]) == 0 ) { found = 1; break; } } // Exit with error if command is not found if( found == 0 ) { fprintf(stderr, "%s: No such command '%s'\n", basename(argv[0]), argv[argi]); return 5; } // Read configuration file cfg = ReadConfig("EUREPHIADM_CONFIG", "eurephiadm.cfg"); if( cfg == NULL ) { fprintf(stderr, "No configuration file found.\n"); return 2; } // If function do not need a logged in session, go a head process it now and exit if( call_fnc->need_session == 0 ) { rc = call_fnc->function(NULL, NULL, cfg, cmdargc, cmdargv); eFree_values(NULL, cfg); return rc; } // // Load database driver, setup a context and create or reuse an open session // and then call the command's function // // Create a eurephia context and load database driver ctx = eurephiaCTX_init(logfile, loglevel, cfg); if( ctx == NULL ) { fprintf(stderr, "Could not initialise a eurephia context.\n"); return 3; } // Check if we have XSLT path available, if not setup a default path if( eGet_value(cfg, "eurephiadm_xslt_path") == NULL ) { eAdd_value(ctx, cfg, "eurephiadm_xslt_path", EUREPHIADM_XSLT_PATH); } // Connect to the database dbparams = eGet_value(cfg, "database_params"); if( !eurephia_ConnectDB(ctx, dbparams) ) { return 4; } // Load session file, if it exists. (reuse open session) if( (sesskey_file = read_session_file(ctx)) == NULL ) { // No session file - go straight to login if( strcmp(call_fnc->command, "logout") == 0) { fprintf(stderr, "You are already logged out\n"); rc = 0; goto exit; } session = do_login(ctx, cfg, call_fnc->accesslvl); if( session == NULL ) { fprintf(stderr, "Login failed\n"); } } else { // If we are logging out, do so here - without checking the session if( strcmp(call_fnc->command, "logout") == 0) { char *logout_argv[] = { sesskey_file }; rc = cmd_Logout(ctx, NULL, cfg, 0, logout_argv); remove_session_file(ctx); free_nullsafe(sesskey_file); goto exit; } // Session file found, check if it still is a valid session if( eDBadminValidateSession(ctx, sesskey_file, call_fnc->accesslvl) ) {; // If valid, load this session session = create_session(ctx, sesskey_file); } else { // If not valid, remove session file and go to login remove_session_file(ctx); session = do_login(ctx, cfg, call_fnc->accesslvl); if( session == NULL ) { fprintf(stderr, "Login failed\n"); } } } free_nullsafe(sesskey_file); // If we have an open session now, call the requested command if(session != NULL ) { char *argstr = NULL; // Write session info to a file if( !write_session_file(ctx, session) ) { eurephia_log(ctx, LOG_ERROR, 0, "Could not write session file. Login needed for actions"); }; // Execute the requested command rc = call_fnc->function(ctx, session, cfg, cmdargc, cmdargv); argstr = args2string(cmdargc, cmdargv); eurephia_log(ctx, LOG_INFO, 0, "Command: %s (result: %i)", argstr, rc); free_nullsafe(argstr); // Remove session info from memory eDBfree_session(ctx, session); } else { // If not an open session, make sure the session file is gone remove_session_file(ctx); } exit: // Disconnect from the database, and remove config and our context before exiting eFree_values(ctx, cfg); eDBdisconnect(ctx); eurephiaCTX_destroy(ctx); return rc; }