bool simulation::execute(string dna, uint32 id) { int status, ret; pid_t pid; string args; setup_input_file(dna, id); if (!file_exists(get_bin_path(id).c_str())) { INFO("verbose", "* simulation: simulator binary does not exists.\n"); exit(0); } pid = fork(); // con vfork gdb si blocca if (pid == 0) { int fd; ret = chdir((char *)get_sim_path(id).c_str()); if((fd = open("/dev/null", O_RDWR | O_CREAT, 0777)) == -1) { perror("open"); _exit(0); } dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); close(fd); ret = execle(get_bin_path(id).c_str(), conf->get_string_config(CONFIG_SIMULATOR_BIN).c_str(), "-N", "1", "-a", conf->get_string_config(CONFIG_TEST_FILE_OUT).c_str() , NULL, environ); perror("execle"); // qui non ci arriva mai ( si spera :D ) _exit(0); } else if (pid == -1) { perror("fork"); return false; } waitpid(pid, &status, 0); return true; }
static bool build_linux_export(export_config *conf) { char *zipname = get_export_zip_name(conf, "linux"); if (am_file_exists(zipname)) am_delete_file(zipname); char *binpath64 = get_bin_path(conf, "linux64"); if (binpath64 == NULL) return false; char *binpath32 = get_bin_path(conf, "linux32"); if (binpath32 == NULL) return false; const char *name = conf->appshortname; bool ok = add_files_to_zip_renamed(zipname, am_opt_data_dir, "*.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath64, "amulet_license.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath64, "amulet", name, name, ".x86_64", true, true, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath32, "amulet", name, name, ".i686", true, true, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, ".", conf->pakfile, name, "data.pak", NULL, false, false, ZIP_PLATFORM_UNIX) && true; printf("%s\n", zipname); free(zipname); free(binpath32); free(binpath64); return ok; }
static bool build_ios_export(export_config *conf) { char *zipname = get_export_zip_name(conf, "ios"); if (am_file_exists(zipname)) am_delete_file(zipname); char *binpath = get_bin_path(conf, "ios"); if (binpath == NULL) return true; if (!create_ios_info_plist(binpath, AM_TMP_DIR AM_PATH_SEP_STR "Info.plist", conf)) return false; if (!create_ios_pkginfo(AM_TMP_DIR AM_PATH_SEP_STR "PkgInfo")) return false; if (!create_ios_icon_files(AM_TMP_DIR, conf)) return false; if (!create_ios_launch_images(AM_TMP_DIR, conf)) return false; const char *name = conf->shortname; char *appdir = am_format("Payload/%s.app", name); bool ok = add_files_to_dist(zipname, am_opt_data_dir, "*.txt", appdir, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, binpath, "amulet_license.txt", appdir, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, binpath, "amulet", appdir, name, NULL, true, true, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, ".", conf->pakfile, appdir, "data.pak", NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "Info.plist", appdir, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "PkgInfo", appdir, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "Icon.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "*****@*****.**", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon40.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon57.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon72.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon76.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon80.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon114.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon120.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon144.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon152.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "icon180.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "iTunesArtwork", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "Default.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "*****@*****.**", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "*****@*****.**", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "*****@*****.**", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "*****@*****.**", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "Default-Landscape@2x~ipad.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "Default-Landscape~ipad.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "Default-Portrait@2x~ipad.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && add_files_to_dist(zipname, AM_TMP_DIR, "Default-Portrait~ipad.png", appdir, NULL, NULL, false, false, ZIP_PLATFORM_UNIX) && create_ios_lproj_dirs(zipname, appdir, conf) && true; free(appdir); am_delete_file(AM_TMP_DIR AM_PATH_SEP_STR "Info.plist"); am_delete_file(AM_TMP_DIR AM_PATH_SEP_STR "PkgInfo"); printf("Generated %s\n", zipname); free(zipname); free(binpath); return ok; }
static bool build_html_export(export_config *conf) { char *zipname = get_export_zip_name(conf, "html"); if (am_file_exists(zipname)) am_delete_file(zipname); char *binpath = get_bin_path(conf, "html"); if (binpath == NULL) return false; const char *name = conf->appshortname; bool ok = add_files_to_zip_renamed(zipname, am_opt_data_dir, "*.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath, "amulet_license.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath, "amulet.js", name, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath, "player.html", name, "index.html", NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, ".", conf->pakfile, name, "data.pak", NULL, false, false, ZIP_PLATFORM_UNIX) && true; printf("%s\n", zipname); free(zipname); free(binpath); return ok; }
static bool build_windows_export(export_config *conf) { char *zipname = get_export_zip_name(conf, "windows"); if (am_file_exists(zipname)) am_delete_file(zipname); char *binpath = get_bin_path(conf, "msvc32"); if (binpath == NULL) return true; const char *name = conf->shortname; bool ok = add_files_to_dist(zipname, am_opt_data_dir, "*.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_DOS) && add_files_to_dist(zipname, binpath, "amulet_license.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_DOS) && add_files_to_dist(zipname, binpath, "amulet.exe", name, name, ".exe", true, true, ZIP_PLATFORM_DOS) && add_files_to_dist(zipname, binpath, "*.dll", name, NULL, NULL, true, true, ZIP_PLATFORM_DOS) && add_files_to_dist(zipname, ".", conf->pakfile, name, "data.pak", NULL, false, false, ZIP_PLATFORM_DOS) && true; printf("Generated %s\n", zipname); free(zipname); free(binpath); return ok; }
static bool build_mac_export(export_config *conf) { char *zipname = get_export_zip_name(conf, "mac"); if (am_file_exists(zipname)) am_delete_file(zipname); char *binpath = get_bin_path(conf, "osx"); if (binpath == NULL) return false; if (!create_mac_info_plist(AM_TMP_DIR "/Info.plist", conf)) return false; const char *name = conf->appshortname; bool ok = add_files_to_zip_renamed(zipname, am_opt_data_dir, "*.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath, "amulet_license.txt", name, NULL, NULL, true, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, binpath, "amulet", name, name, ".app/Contents/MacOS/amulet", true, true, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, ".", conf->pakfile, name, name, ".app/Contents/Resources/data.pak", false, false, ZIP_PLATFORM_UNIX) && add_files_to_zip_renamed(zipname, AM_TMP_DIR, "Info.plist", name, name, ".app/Contents/Info.plist", true, false, ZIP_PLATFORM_UNIX) && true; am_delete_file(AM_TMP_DIR "/Info.plist"); printf("%s\n", zipname); free(zipname); free(binpath); return ok; }
int main(int argc, char **av) { char *prog = *av; opt *set = NULL; int i, grpdebug = 0, debug = 0, setlen = 0, listing = 0; str err = MAL_SUCCEED; char prmodpath[FILENAME_MAX]; const char *modpath = NULL; char *binpath = NULL; str *monet_script; char *dbpath = NULL; char *dbextra = NULL; int verbosity = 0; static struct option long_options[] = { { "config", required_argument, NULL, 'c' }, { "dbpath", required_argument, NULL, 0 }, { "dbextra", required_argument, NULL, 0 }, { "daemon", required_argument, NULL, 0 }, { "debug", optional_argument, NULL, 'd' }, { "help", no_argument, NULL, '?' }, { "version", no_argument, NULL, 0 }, { "verbose", optional_argument, NULL, 'v' }, { "readonly", no_argument, NULL, 'r' }, { "single-user", no_argument, NULL, 0 }, { "set", required_argument, NULL, 's' }, { "threads", no_argument, NULL, 0 }, { "memory", no_argument, NULL, 0 }, { "properties", no_argument, NULL, 0 }, { "io", no_argument, NULL, 0 }, { "transactions", no_argument, NULL, 0 }, { "trace", optional_argument, NULL, 't' }, { "modules", no_argument, NULL, 0 }, { "algorithms", no_argument, NULL, 0 }, { "optimizers", no_argument, NULL, 0 }, { "performance", no_argument, NULL, 0 }, { "forcemito", no_argument, NULL, 0 }, { "heaps", no_argument, NULL, 0 }, { NULL, 0, NULL, 0 } }; #if defined(_MSC_VER) && defined(__cplusplus) set_terminate(mserver_abort); #endif #ifdef _MSC_VER _CrtSetReportMode(_CRT_ERROR, 0); _CrtSetReportMode(_CRT_ASSERT, 0); _set_invalid_parameter_handler(mserver_invalid_parameter_handler); #ifdef _TWO_DIGIT_EXPONENT _set_output_format(_TWO_DIGIT_EXPONENT); #endif #endif if (setlocale(LC_CTYPE, "") == NULL) { fprintf(stderr, "cannot set locale\n"); exit(1); } if (getcwd(monet_cwd, FILENAME_MAX - 1) == NULL) { perror("pwd"); fprintf(stderr,"monet_init: could not determine current directory\n"); exit(-1); } /* retrieve binpath early (before monet_init) because some * implementations require the working directory when the binary was * called */ binpath = get_bin_path(); if (!(setlen = mo_builtin_settings(&set))) usage(prog, -1); for (;;) { int option_index = 0; int c = getopt_long(argc, av, "c:d::rs:t::v::?", long_options, &option_index); if (c == -1) break; switch (c) { case 0: if (strcmp(long_options[option_index].name, "dbpath") == 0) { size_t optarglen = strlen(optarg); /* remove trailing directory separator */ while (optarglen > 0 && (optarg[optarglen - 1] == '/' || optarg[optarglen - 1] == '\\')) optarg[--optarglen] = '\0'; dbpath = absolute_path(optarg); if( dbpath == NULL) fprintf(stderr, "#error: can not allocate memory for dbpath\n"); else setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_dbpath", dbpath); break; } if (strcmp(long_options[option_index].name, "dbextra") == 0) { if (dbextra) fprintf(stderr, "#warning: ignoring multiple --dbextra arguments\n"); else dbextra = optarg; break; } #ifdef HAVE_CONSOLE if (strcmp(long_options[option_index].name, "daemon") == 0) { setlen = mo_add_option(&set, setlen, opt_cmdline, "monet_daemon", optarg); break; } #endif if (strcmp(long_options[option_index].name, "single-user") == 0) { setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_single_user", "yes"); break; } if (strcmp(long_options[option_index].name, "version") == 0) { monet_version(); exit(0); } /* debugging options */ if (strcmp(long_options[option_index].name, "properties") == 0) { grpdebug |= GRPproperties; break; } if (strcmp(long_options[option_index].name, "algorithms") == 0) { grpdebug |= GRPalgorithms; break; } if (strcmp(long_options[option_index].name, "optimizers") == 0) { grpdebug |= GRPoptimizers; break; } if (strcmp(long_options[option_index].name, "forcemito") == 0) { grpdebug |= GRPforcemito; break; } if (strcmp(long_options[option_index].name, "performance") == 0) { grpdebug |= GRPperformance; break; } if (strcmp(long_options[option_index].name, "io") == 0) { grpdebug |= GRPio; break; } if (strcmp(long_options[option_index].name, "memory") == 0) { grpdebug |= GRPmemory; break; } if (strcmp(long_options[option_index].name, "modules") == 0) { grpdebug |= GRPmodules; break; } if (strcmp(long_options[option_index].name, "transactions") == 0) { grpdebug |= GRPtransactions; break; } if (strcmp(long_options[option_index].name, "threads") == 0) { grpdebug |= GRPthreads; break; } if (strcmp(long_options[option_index].name, "trace") == 0) { mal_trace = 1; break; } if (strcmp(long_options[option_index].name, "heaps") == 0) { grpdebug |= GRPheaps; break; } usage(prog, -1); /* not reached */ case 'c': /* coverity[var_deref_model] */ setlen = mo_add_option(&set, setlen, opt_cmdline, "config", optarg); break; case 'd': if (optarg) { char *endarg; debug |= strtol(optarg, &endarg, 10); if (*endarg != '\0') { fprintf(stderr, "ERROR: wrong format for --debug=%s\n", optarg); usage(prog, -1); } } else { debug |= 1; } break; case 'r': setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_readonly", "yes"); break; case 's': { /* should add option to a list */ /* coverity[var_deref_model] */ char *tmp = strchr(optarg, '='); if (tmp) { *tmp = '\0'; setlen = mo_add_option(&set, setlen, opt_cmdline, optarg, tmp + 1); } else fprintf(stderr, "ERROR: wrong format %s\n", optarg); } break; case 't': mal_trace = 1; break; case 'v': if (optarg) { char *endarg; verbosity = (int) strtol(optarg, &endarg, 10); if (*endarg != '\0') { fprintf(stderr, "ERROR: wrong format for --verbose=%s\n", optarg); usage(prog, -1); } } else { verbosity++; } break; case '?': /* a bit of a hack: look at the option that the current `c' is based on and see if we recognize it: if -? or --help, exit with 0, else with -1 */ usage(prog, strcmp(av[optind - 1], "-?") == 0 || strcmp(av[optind - 1], "--help") == 0 ? 0 : -1); default: fprintf(stderr, "ERROR: getopt returned character " "code '%c' 0%o\n", c, (uint8_t) c); usage(prog, -1); } } if (!(setlen = mo_system_config(&set, setlen))) usage(prog, -1); GDKsetdebug(debug | grpdebug); /* add the algorithm tracers */ if (debug) mo_print_options(set, setlen); GDKsetverbose(verbosity); monet_script = (str *) malloc(sizeof(str) * (argc + 1)); if (monet_script == NULL) { fprintf(stderr, "!ERROR: cannot allocate memory for script \n"); exit(1); } i = 0; while (optind < argc) { monet_script[i] = absolute_path(av[optind]); if (monet_script[i] == NULL) { fprintf(stderr, "!ERROR: cannot allocate memory for script \n"); exit(1); } i++; optind++; } monet_script[i] = NULL; if (!dbpath) { dbpath = absolute_path(mo_find_option(set, setlen, "gdk_dbpath")); if (!dbpath) { fprintf(stderr, "!ERROR: cannot allocate memory for database directory \n"); exit(1); } } if (BBPaddfarm(dbpath, 1 << PERSISTENT) != GDK_SUCCEED || BBPaddfarm(dbextra ? dbextra : dbpath, 1 << TRANSIENT) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: cannot add farm\n"); exit(1); } if (GDKcreatedir(dbpath) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: cannot create directory for %s\n", dbpath); exit(1); } GDKfree(dbpath); if (monet_init(set, setlen) == 0) { mo_free_options(set, setlen); if (GDKerrbuf && *GDKerrbuf) fprintf(stderr, "%s\n", GDKerrbuf); exit(1); } mo_free_options(set, setlen); if (GDKsetenv("monet_version", GDKversion()) != GDK_SUCCEED || GDKsetenv("monet_release", #ifdef MONETDB_RELEASE MONETDB_RELEASE #else "unreleased" #endif ) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: GDKsetenv failed\n"); exit(1); } if ((modpath = GDKgetenv("monet_mod_path")) == NULL) { /* start probing based on some heuristics given the binary * location: * bin/mserver5 -> ../ * libX/monetdb5/lib/ * probe libX = lib, lib32, lib64, lib/64 */ size_t pref; /* "remove" common prefix of configured BIN and LIB * directories from LIBDIR */ for (pref = 0; LIBDIR[pref] != 0 && BINDIR[pref] == LIBDIR[pref]; pref++) ; const char *libdirs[] = { &LIBDIR[pref], "lib", "lib64", "lib/64", "lib32", NULL, }; struct stat sb; if (binpath != NULL) { char *p = strrchr(binpath, DIR_SEP); if (p != NULL) *p = '\0'; p = strrchr(binpath, DIR_SEP); if (p != NULL) { *p = '\0'; for (i = 0; libdirs[i] != NULL; i++) { int len = snprintf(prmodpath, sizeof(prmodpath), "%s%c%s%cmonetdb5", binpath, DIR_SEP, libdirs[i], DIR_SEP); if (len == -1 || len >= FILENAME_MAX) continue; if (stat(prmodpath, &sb) == 0) { modpath = prmodpath; break; } } } else { printf("#warning: unusable binary location, " "please use --set monet_mod_path=/path/to/... to " "allow finding modules\n"); fflush(NULL); } } else { printf("#warning: unable to determine binary location, " "please use --set monet_mod_path=/path/to/... to " "allow finding modules\n"); fflush(NULL); } if (modpath != NULL && GDKsetenv("monet_mod_path", modpath) != GDK_SUCCEED) { fprintf(stderr, "!ERROR: GDKsetenv failed\n"); exit(1); } } /* configure sabaoth to use the right dbpath and active database */ msab_dbpathinit(GDKgetenv("gdk_dbpath")); /* wipe out all cruft, if left over */ if ((err = msab_wildRetreat()) != NULL) { /* just swallow the error */ free(err); } /* From this point, the server should exit cleanly. Discussion: * even earlier? Sabaoth here registers the server is starting up. */ if ((err = msab_registerStarting()) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } #ifdef HAVE_SIGACTION { struct sigaction sa; (void) sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; if (sigaction(SIGINT, &sa, NULL) == -1 || sigaction(SIGQUIT, &sa, NULL) == -1 || sigaction(SIGTERM, &sa, NULL) == -1) { fprintf(stderr, "!unable to create signal handlers\n"); } } #else #ifdef _MSC_VER if (!SetConsoleCtrlHandler(winhandler, TRUE)) fprintf(stderr, "!unable to create console control handler\n"); #else if(signal(SIGINT, handler) == SIG_ERR) fprintf(stderr, "!unable to create signal handlers\n"); #ifdef SIGQUIT if(signal(SIGQUIT, handler) == SIG_ERR) fprintf(stderr, "!unable to create signal handlers\n"); #endif if(signal(SIGTERM, handler) == SIG_ERR) fprintf(stderr, "!unable to create signal handlers\n"); #endif #endif { str lang = "mal"; /* we inited mal before, so publish its existence */ if ((err = msab_marchScenario(lang)) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } } { /* unlock the vault, first see if we can find the file which * holds the secret */ char secret[1024]; char *secretp = secret; FILE *secretf; size_t len; if (GDKgetenv("monet_vault_key") == NULL) { /* use a default (hard coded, non safe) key */ snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8"); } else { if ((secretf = fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) { fprintf(stderr, "unable to open vault_key_file %s: %s\n", GDKgetenv("monet_vault_key"), strerror(errno)); /* don't show this as a crash */ msab_registerStop(); exit(1); } len = fread(secret, 1, sizeof(secret), secretf); secret[len] = '\0'; len = strlen(secret); /* secret can contain null-bytes */ if (len == 0) { fprintf(stderr, "vault key has zero-length!\n"); /* don't show this as a crash */ msab_registerStop(); exit(1); } else if (len < 5) { fprintf(stderr, "#warning: your vault key is too short " "(%zu), enlarge your vault key!\n", len); } fclose(secretf); } if ((err = AUTHunlockVault(secretp)) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); fprintf(stderr, "%s\n", err); freeException(err); exit(1); } } /* make sure the authorisation BATs are loaded */ if ((err = AUTHinitTables(NULL)) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); fprintf(stderr, "%s\n", err); freeException(err); exit(1); } if (mal_init()) { /* don't show this as a crash */ msab_registerStop(); return 0; } if((err = MSinitClientPrg(mal_clients, "user", "main")) != MAL_SUCCEED) { msab_registerStop(); fprintf(stderr, "%s\n", err); freeException(err); exit(1); } emergencyBreakpoint(); for (i = 0; monet_script[i]; i++) { str msg = evalFile(monet_script[i], listing); /* check for internal exception message to terminate */ if (msg) { if (strcmp(msg, "MALException:client.quit:Server stopped.") == 0) mal_exit(0); fprintf(stderr, "#%s: %s\n", monet_script[i], msg); freeException(msg); } GDKfree(monet_script[i]); monet_script[i] = 0; } free(monet_script); if ((err = msab_registerStarted()) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } #ifdef HAVE_CONSOLE if (!monet_daemon) { MSserveClient(mal_clients); } else #endif while (!interrupted && !GDKexiting()) { MT_sleep_ms(100); } /* mal_exit calls exit, so statements after this call will * never get reached */ mal_exit(0); return 0; }
int main(int argc, char **av) { char *prog = *av; opt *set = NULL; int idx = 0, grpdebug = 0, debug = 0, setlen = 0, listing = 0, i = 0; str dbinit = NULL; str err = MAL_SUCCEED; char prmodpath[1024]; char *modpath = NULL; char *binpath = NULL; str *monet_script; static struct option long_options[] = { { "config", 1, 0, 'c' }, { "dbpath", 1, 0, 0 }, { "dbinit", 1, 0, 0 }, { "debug", 2, 0, 'd' }, { "help", 0, 0, '?' }, { "version", 0, 0, 0 }, { "readonly", 0, 0, 'r' }, { "set", 1, 0, 's' }, { "threads", 0, 0, 0 }, { "memory", 0, 0, 0 }, { "properties", 0, 0, 0 }, { "io", 0, 0, 0 }, { "transactions", 0, 0, 0 }, { "trace", 2, 0, 't' }, { "modules", 0, 0, 0 }, { "algorithms", 0, 0, 0 }, { "optimizers", 0, 0, 0 }, { "performance", 0, 0, 0 }, #if 0 { "xproperties", 0, 0, 0 }, #endif { "forcemito", 0, 0, 0 }, { "heaps", 0, 0, 0 }, { 0, 0, 0, 0 } }; #if defined(_MSC_VER) && defined(__cplusplus) set_terminate(mserver_abort); #endif if (setlocale(LC_CTYPE, "") == NULL) { GDKfatal("cannot set locale\n"); } #ifdef HAVE_MALLOPT if (malloc_init) { /* for (Red Hat) Linux (6.2) unused and ignored at least as of glibc-2.1.3-15 */ /* for (Red Hat) Linux (8) used at least as of glibc-2.2.93-5 */ if (mallopt(M_MXFAST, 192)) { fprintf(stderr, "!monet: mallopt(M_MXFAST,192) fails.\n"); } #ifdef M_BLKSZ if (mallopt(M_BLKSZ, 8 * 1024)) { fprintf(stderr, "!monet: mallopt(M_BLKSZ,8*1024) fails.\n"); } #endif } malloc_init = 0; #else (void) malloc_init; /* still unused */ #endif if (getcwd(monet_cwd, PATHLENGTH - 1) == NULL) { perror("pwd"); GDKfatal("monet_init: could not determine current directory\n"); } /* retrieve binpath early (before monet_init) because some * implementations require the working directory when the binary was * called */ binpath = get_bin_path(); if (!(setlen = mo_builtin_settings(&set))) usage(prog, -1); setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_single_user", "yes"); for (;;) { int option_index = 0; int c = getopt_long(argc, av, "c:d::rs:t::?", long_options, &option_index); if (c == -1) break; switch (c) { case 0: if (strcmp(long_options[option_index].name, "dbpath") == 0) { size_t optarglen = strlen(optarg); /* remove trailing directory separator */ while (optarglen > 0 && (optarg[optarglen - 1] == '/' || optarg[optarglen - 1] == '\\')) optarg[--optarglen] = '\0'; setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_dbpath", optarg); break; } if (strcmp(long_options[option_index].name, "dbinit") == 0) { if (dbinit) fprintf(stderr, "#warning: ignoring multiple --dbinit argument\n"); else dbinit = optarg; break; } if (strcmp(long_options[option_index].name, "version") == 0) { monet_version(); exit(0); } /* debugging options */ if (strcmp(long_options[option_index].name, "properties") == 0) { grpdebug |= GRPproperties; break; } if (strcmp(long_options[option_index].name, "algorithms") == 0) { grpdebug |= GRPalgorithms; break; } if (strcmp(long_options[option_index].name, "optimizers") == 0) { grpdebug |= GRPoptimizers; break; } #if 0 if (strcmp(long_options[option_index].name, "xproperties") == 0) { grpdebug |= GRPxproperties; break; } #endif if (strcmp(long_options[option_index].name, "forcemito") == 0) { grpdebug |= GRPforcemito; break; } if (strcmp(long_options[option_index].name, "performance") == 0) { grpdebug |= GRPperformance; break; } if (strcmp(long_options[option_index].name, "io") == 0) { grpdebug |= GRPio; break; } if (strcmp(long_options[option_index].name, "memory") == 0) { grpdebug |= GRPmemory; break; } if (strcmp(long_options[option_index].name, "modules") == 0) { grpdebug |= GRPmodules; break; } if (strcmp(long_options[option_index].name, "transactions") == 0) { grpdebug |= GRPtransactions; break; } if (strcmp(long_options[option_index].name, "threads") == 0) { grpdebug |= GRPthreads; break; } if (strcmp(long_options[option_index].name, "trace") == 0) { mal_trace = optarg? optarg:"ISTest"; break; } if (strcmp(long_options[option_index].name, "heaps") == 0) { grpdebug |= GRPheaps; break; } usage(prog, -1); /* not reached */ case 'c': setlen = mo_add_option(&set, setlen, opt_cmdline, "config", optarg); break; case 'd': if (optarg) { debug |= strtol(optarg, NULL, 10); } else { debug |= 1; } break; case 'r': setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_readonly", "yes"); break; case 's': { /* should add option to a list */ char *tmp = strchr(optarg, '='); if (tmp) { *tmp = '\0'; setlen = mo_add_option(&set, setlen, opt_cmdline, optarg, tmp + 1); } else fprintf(stderr, "ERROR: wrong format %s\n", optarg); } break; case 't': mal_trace = optarg? optarg:"ISTest"; break; case '?': /* a bit of a hack: look at the option that the current `c' is based on and see if we recognize it: if -? or --help, exit with 0, else with -1 */ usage(prog, strcmp(av[optind - 1], "-?") == 0 || strcmp(av[optind - 1], "--help") == 0 ? 0 : -1); default: fprintf(stderr, "ERROR: getopt returned character " "code '%c' 0%o\n", c, c); usage(prog, -1); } } if (!(setlen = mo_system_config(&set, setlen))) usage(prog, -1); if (debug || grpdebug) { long_str buf; if (debug) mo_print_options(set, setlen); debug |= grpdebug; /* add the algorithm tracers */ snprintf(buf, sizeof(long_str) - 1, "%d", debug); setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_debug", buf); } #ifdef RDEBUG printf("parameter ok\n"); #endif monet_script = (str *) malloc(sizeof(str) * (argc + 1)); if (monet_script) { monet_script[idx] = NULL; while (optind < argc) { monet_script[idx] = absolute_path(av[optind]); monet_script[idx + 1] = NULL; optind++; idx++; } } if (monet_init(set, setlen) == 0) { mo_free_options(set, setlen); return 0; } mo_free_options(set, setlen); #ifdef RDEBUG printf("monet_init ok\n"); #endif GDKsetenv("monet_version", VERSION); GDKsetenv("monet_release", MONETDB_RELEASE); if ((modpath = GDKgetenv("monet_mod_path")) == NULL) { /* start probing based on some heuristics given the binary * location: * bin/mserver5 -> ../ * libX/monetdb5/lib/ * probe libX = lib, lib32, lib64, lib/64 */ char *libdirs[] = { "lib", "lib64", "lib/64", "lib32", NULL }; size_t i; struct stat sb; if (binpath != NULL) { char *p = strrchr(binpath, DIR_SEP); if (p != NULL) *p = '\0'; p = strrchr(binpath, DIR_SEP); if (p != NULL) { *p = '\0'; for (i = 0; libdirs[i] != NULL; i++) { snprintf(prmodpath, sizeof(prmodpath), "%s%c%s%cmonetdb5", binpath, DIR_SEP, libdirs[i], DIR_SEP); if (stat(prmodpath, &sb) == 0) { modpath = prmodpath; break; } } } else { printf("#warning: unusable binary location, " "please use --set monet_mod_path=/path/to/... to " "allow finding modules\n"); fflush(NULL); } } else { printf("#warning: unable to determine binary location, " "please use --set monet_mod_path=/path/to/... to " "allow finding modules\n"); fflush(NULL); } if (modpath != NULL) GDKsetenv("monet_mod_path", modpath); } #ifdef RDEBUG printf("modpath ok\n"); #endif /* configure sabaoth to use the right dbpath and active database */ msab_dbpathinit(GDKgetenv("gdk_dbpath")); /* wipe out all cruft, if left over */ if ((err = msab_wildRetreat()) != NULL) { /* just swallow the error */ free(err); } /* From this point, the server should exit cleanly. Discussion: * even earlier? Sabaoth here registers the server is starting up. */ if ((err = msab_registerStarting()) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } #ifdef RDEBUG printf("some stuff\n"); #endif #ifdef HAVE_SIGACTION { struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; if ( sigaction(SIGINT, &sa, NULL) == -1 || sigaction(SIGQUIT, &sa, NULL) == -1 || sigaction(SIGTERM, &sa, NULL) == -1) { fprintf(stderr, "!unable to create signal handlers\n"); } } #else signal(SIGINT, handler); #ifdef SIGQUIT signal(SIGQUIT, handler); #endif signal(SIGTERM, handler); #endif { str lang = "mal"; /* we inited mal before, so publish its existence */ if ((err = msab_marchScenario(lang)) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } } #ifdef RDEBUG printf("scenario ok\n"); #endif { /* unlock the vault, first see if we can find the file which * holds the secret */ char secret[1024]; char *secretp = secret; FILE *secretf; size_t len; if (GDKgetenv("monet_vault_key") == NULL) { /* use a default (hard coded, non safe) key */ snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8"); } else { if ((secretf = fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) { snprintf(secret, sizeof(secret), "unable to open vault_key_file %s: %s", GDKgetenv("monet_vault_key"), strerror(errno)); /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", secret); } len = fread(secret, 1, sizeof(secret), secretf); secret[len] = '\0'; len = strlen(secret); /* secret can contain null-bytes */ if (len == 0) { snprintf(secret, sizeof(secret), "vault key has zero-length!"); /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", secret); } else if (len < 5) { fprintf(stderr, "#warning: your vault key is too short " "(" SZFMT "), enlarge your vault key!\n", len); } fclose(secretf); } if ((err = AUTHunlockVault(&secretp)) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", err); } } /* make sure the authorisation BATs are loaded */ if ((err = AUTHinitTables()) != MAL_SUCCEED) { /* don't show this as a crash */ msab_registerStop(); GDKfatal("%s", err); } #ifdef RDEBUG printf("vaultkey ok\n"); #endif if (mal_init()) { /* don't show this as a crash */ msab_registerStop(); return 0; } #ifdef RDEBUG printf("mal_init ok\n"); #endif #if (0) if (!loadLibrary("lib_leaker", TRUE)) return 42; #endif #ifdef RDEBUG printf("lib_leaker ok\n"); #endif if (GDKgetenv("mal_listing")) sscanf(GDKgetenv("mal_listing"), "%d", &listing); MSinitClientPrg(mal_clients, "user", "main"); if (dbinit == NULL) dbinit = GDKgetenv("dbinit"); if (dbinit) callString(mal_clients, dbinit, listing); #ifdef RDEBUG printf("MSinitClientPrg ok\n"); #endif emergencyBreakpoint(); if ((err = compileOptimizer(mal_clients, "leaker_pipe")) != MAL_SUCCEED) mnstr_printf(mal_clients->fdout, "OPT_COMPILE: %s\n", err); //callString(mal_clients, "sql.start();\n", 0); if (monet_script) for (i = 0; monet_script[i]; i++) { str msg = evalFile(mal_clients, monet_script[i], listing); /* check for internal exception message to terminate */ if (msg) { if (strcmp(msg, "MALException:client.quit:Server stopped.") == 0) mal_exit(); fprintf(stderr, "#%s: %s\n", monet_script[i], msg); GDKfree(msg); } GDKfree(monet_script[i]); monet_script[i] = 0; } if ((err = msab_registerStarted()) != NULL) { /* throw the error at the user, but don't die */ fprintf(stderr, "!%s\n", err); free(err); } if (monet_script) free(monet_script); MSserveClient(mal_clients); /* mal_exit calls MT_global_exit, so statements after this call will * never get reached */ mal_exit(); return 0; }
int main(int argc, char *argv[]) { err e; int argp; char dbfarm[1024]; char *pidfilename = NULL; char *p; FILE *pidfile = NULL; char control_usock[1024]; char mapi_usock[1024]; dpair d = NULL; struct _dpair dpcons; struct _dpair dpmero; struct _dpair dpdisc; struct _dpair dpcont; int pfd[2]; pthread_t tid = 0; struct sigaction sa; int ret; int lockfd = -1; int sock = -1; int usock = -1; int unsock = -1; int socku = -1; unsigned short port = 0; char discovery = 0; struct stat sb; FILE *oerr = NULL; pthread_mutexattr_t mta; int thret; char merodontfork = 0; confkeyval ckv[] = { {"logfile", strdup("merovingian.log"), 0, STR}, {"pidfile", strdup("merovingian.pid"), 0, STR}, {"sockdir", strdup("/tmp"), 0, STR}, {"port", strdup(MERO_PORT), atoi(MERO_PORT), INT}, {"exittimeout", strdup("60"), 60, INT}, {"forward", strdup("proxy"), 0, OTHER}, {"discovery", strdup("true"), 1, BOOLEAN}, {"discoveryttl", strdup("600"), 600, INT}, {"control", strdup("false"), 0, BOOLEAN}, {"passphrase", NULL, 0, STR}, { NULL, NULL, 0, INVALID} }; confkeyval *kv; int retfd = -1; /* seed the randomiser for when we create a database, send responses * to HELO, etc */ srand(time(NULL)); /* figure out our hostname */ gethostname(_mero_hostname, 128); /* where is the mserver5 binary we fork on demand? * first try to locate it based on our binary location, fall-back to * hardcoded bin-dir */ _mero_mserver = get_bin_path(); if (_mero_mserver != NULL) { /* replace the trailing monetdbd by mserver5, fits nicely since * they happen to be of same length */ char *s = strrchr(_mero_mserver, '/'); if (s != NULL && strcmp(s + 1, "monetdbd") == 0) { s++; *s++ = 'm'; *s++ = 's'; *s++ = 'e'; *s++ = 'r'; *s++ = 'v'; *s++ = 'e'; *s++ = 'r'; *s++ = '5'; if (stat(_mero_mserver, &sb) == -1) _mero_mserver = NULL; } } /* setup default database properties, constants: unlike historical * versions, we do not want changing defaults any more */ _mero_db_props = getDefaultProps(); kv = findConfKey(_mero_db_props, "shared"); kv->val = strdup("yes"); kv = findConfKey(_mero_db_props, "readonly"); kv->val = strdup("no"); kv = findConfKey(_mero_db_props, "nclients"); kv->val = strdup("64"); kv = findConfKey(_mero_db_props, "type"); kv->val = strdup("database"); kv = findConfKey(_mero_db_props, "optpipe"); kv->val = strdup("default_pipe"); { /* nrthreads */ int ncpus = -1; char cnt[8]; #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) /* this works on Linux, Solaris and AIX */ ncpus = sysconf(_SC_NPROCESSORS_ONLN); #elif defined(HAVE_SYS_SYSCTL_H) && defined(HW_NCPU) /* BSD */ size_t len = sizeof(int); int mib[3]; /* Everyone should have permission to make this call, * if we get a failure something is really wrong. */ mib[0] = CTL_HW; mib[1] = HW_NCPU; mib[2] = -1; sysctl(mib, 3, &ncpus, &len, NULL, 0); #elif defined(WIN32) SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); ncpus = sysinfo.dwNumberOfProcessors; #endif if (ncpus > 0) { snprintf(cnt, sizeof(cnt), "%d", ncpus); kv = findConfKey(_mero_db_props, "nthreads"); kv->val = strdup(cnt); } } *dbfarm = '\0'; if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "help") == 0) { exit(command_help(argc - 1, &argv[1])); } else if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "version") == 0) { exit(command_version()); } else if (strcmp(argv[1], "create") == 0) { exit(command_create(argc - 1, &argv[1])); } else if (strcmp(argv[1], "get") == 0) { exit(command_get(ckv, argc - 1, &argv[1])); } else if (strcmp(argv[1], "set") == 0) { exit(command_set(ckv, argc - 1, &argv[1])); } else if (strcmp(argv[1], "start") == 0) { if (argc > 3 && strcmp(argv[2], "-n") == 0) merodontfork = 1; if (argc == 3 + merodontfork) { int len; len = snprintf(dbfarm, sizeof(dbfarm), "%s", argv[2 + merodontfork]); if (len > 0 && (size_t)len >= sizeof(dbfarm)) { Mfprintf(stderr, "fatal: dbfarm exceeds allocated " \ "path length, please file a bug at " \ "http://bugs.monetdb.org/\n"); exit(1); } } else { command_help(argc, argv); exit(1); } } else if (strcmp(argv[1], "stop") == 0) { exit(command_stop(ckv, argc - 1, &argv[1])); } else { fprintf(stderr, "monetdbd: unknown command: %s\n", argv[1]); command_help(0, NULL); exit(1); } } else { command_help(0, NULL); exit(1); } assert(*dbfarm != '\0'); /* fork into background before doing anything more */ if (!merodontfork) { char buf[4]; /* Fork into the background immediately. By doing this our child * can simply do everything it needs to do itself. Via a pipe it * will tell us if it is happy or not. */ if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); return(1); } switch (fork()) { case -1: /* oops, forking went wrong! */ Mfprintf(stderr, "unable to fork into background: %s\n", strerror(errno)); return(1); case 0: /* detach client from controlling tty, we only write to the * pipe to daddy */ if (setsid() < 0) Mfprintf(stderr, "hmmm, can't detach from controlling tty, " "continuing anyway\n"); retfd = open("/dev/null", O_RDONLY); dup2(retfd, 0); close(retfd); close(pfd[0]); /* close unused read end */ retfd = pfd[1]; /* store the write end */ break; default: /* the parent, we want it to die, after we know the child * has a good time */ close(pfd[1]); /* close unused write end */ if (read(pfd[0], &buf, 1) != 1) { Mfprintf(stderr, "unable to retrieve startup status\n"); return(1); } close(pfd[0]); return(buf[0]); /* whatever the child returned, we return */ } } /* use after the logger thread has started */ #define MERO_EXIT(status) if (!merodontfork) { \ char s = status; \ if (write(retfd, &s, 1) != 1 || close(retfd) != 0) { \ Mfprintf(stderr, "could not write to parent\n"); \ } \ if (status != 0) { \ Mfprintf(stderr, "fatal startup condition encountered, " \ "aborting startup\n"); \ goto shutdown; \ } \ } else { \ if (status != 0) { \ Mfprintf(stderr, "fatal startup condition encountered, " \ "aborting startup\n"); \ goto shutdown; \ } \ } /* use before logger thread has started */ #define MERO_EXIT_CLEAN(status) if (!merodontfork) { \ char s = status; \ if (write(retfd, &s, 1) != 1 || close(retfd) != 0) { \ Mfprintf(stderr, "could not write to parent\n"); \ } \ exit(s); \ } else { \ exit(status); \ } /* check if dbfarm actually exists */ if (stat(dbfarm, &sb) == -1) { Mfprintf(stderr, "dbfarm directory '%s' does not exist, " "use monetdbd create first\n", dbfarm); MERO_EXIT_CLEAN(1); } /* chdir to dbfarm so we are at least in a known to exist location */ if (chdir(dbfarm) < 0) { Mfprintf(stderr, "could not move to dbfarm '%s': %s\n", dbfarm, strerror(errno)); MERO_EXIT_CLEAN(1); } /* absolutise dbfarm if it isn't yet (we're in it now) */ if (dbfarm[0] != '/') { if (getcwd(dbfarm, sizeof(dbfarm)) == NULL) { if (errno == ERANGE) { Mfprintf(stderr, "current path exceeds allocated path length" \ "please file a bug at http://bugs.monetdb.org\n"); } else { Mfprintf(stderr, "could not get dbfarm working directory: %s\n", strerror(errno)); } MERO_EXIT_CLEAN(1); } } if (_mero_mserver == NULL) { _mero_mserver = BINDIR "/mserver5"; if (stat(_mero_mserver, &sb) == -1) { /* exit early if this is not going to work well */ Mfprintf(stderr, "cannot stat %s executable: %s\n", _mero_mserver, strerror(errno)); MERO_EXIT_CLEAN(1); } } /* read the merovingian properties from the dbfarm */ if (readProps(ckv, ".") != 0) { Mfprintf(stderr, "cannot find or read properties file, was " "this dbfarm created by `monetdbd create`?\n"); MERO_EXIT_CLEAN(1); } _mero_props = ckv; pidfilename = getConfVal(_mero_props, "pidfile"); p = getConfVal(_mero_props, "forward"); if (strcmp(p, "redirect") != 0 && strcmp(p, "proxy") != 0) { Mfprintf(stderr, "invalid forwarding mode: %s, defaulting to proxy\n", p); kv = findConfKey(_mero_props, "forward"); setConfVal(kv, "proxy"); writeProps(_mero_props, "."); } kv = findConfKey(_mero_props, "port"); if (kv->ival <= 0 || kv->ival > 65535) { Mfprintf(stderr, "invalid port number: %s, defaulting to %s\n", kv->val, MERO_PORT); setConfVal(kv, MERO_PORT); writeProps(_mero_props, "."); } port = (unsigned short)kv->ival; discovery = getConfNum(_mero_props, "discovery"); /* check and trim the hash-algo from the passphrase for easy use * lateron */ kv = findConfKey(_mero_props, "passphrase"); if (kv->val != NULL) { char *h = kv->val + 1; if ((p = strchr(h, '}')) == NULL) { Mfprintf(stderr, "warning: incompatible passphrase (not hashed as " MONETDB5_PASSWDHASH "), disabling passphrase\n"); } else { *p = '\0'; if (strcmp(h, MONETDB5_PASSWDHASH) != 0) { Mfprintf(stderr, "warning: passphrase hash '%s' incompatible, " "expected '%s', disabling passphrase\n", h, MONETDB5_PASSWDHASH); } else { setConfVal(kv, p + 1); } } } /* set up UNIX socket paths for control and mapi */ p = getConfVal(_mero_props, "sockdir"); snprintf(control_usock, sizeof(control_usock), "%s/" CONTROL_SOCK "%d", p, port); snprintf(mapi_usock, sizeof(control_usock), "%s/" MERO_SOCK "%d", p, port); /* lock such that we are alone on this world */ if ((lockfd = MT_lockf(".merovingian_lock", F_TLOCK, 4, 1)) == -1) { /* locking failed */ Mfprintf(stderr, "another monetdbd is already running\n"); MERO_EXIT_CLEAN(1); } else if (lockfd == -2) { /* directory or something doesn't exist */ Mfprintf(stderr, "unable to create %s/.merovingian_lock file: %s\n", dbfarm, strerror(errno)); MERO_EXIT_CLEAN(1); } _mero_topdp = &dpcons; _mero_topdp->pid = 0; _mero_topdp->type = MERO; _mero_topdp->dbname = NULL; /* where should our msg output go to? */ p = getConfVal(_mero_props, "logfile"); /* write to the given file */ _mero_topdp->out = open(p, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); if (_mero_topdp->out == -1) { Mfprintf(stderr, "unable to open '%s': %s\n", p, strerror(errno)); MT_lockf(".merovingian_lock", F_ULOCK, 4, 1); close(lockfd); MERO_EXIT_CLEAN(1); } _mero_topdp->err = _mero_topdp->out; _mero_logfile = fdopen(_mero_topdp->out, "a"); d = _mero_topdp->next = &dpmero; /* redirect stdout */ if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->out = pfd[0]; dup2(pfd[1], 1); close(pfd[1]); /* redirect stderr */ if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } /* before it is too late, save original stderr */ oerr = fdopen(dup(2), "w"); d->err = pfd[0]; dup2(pfd[1], 2); close(pfd[1]); d->pid = getpid(); d->type = MERO; d->dbname = "merovingian"; /* separate entry for the neighbour discovery service */ d = d->next = &dpdisc; if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->out = pfd[0]; _mero_discout = fdopen(pfd[1], "a"); if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->err = pfd[0]; _mero_discerr = fdopen(pfd[1], "a"); d->pid = getpid(); d->type = MERO; d->dbname = "discovery"; d->next = NULL; /* separate entry for the control runner */ d = d->next = &dpcont; if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->out = pfd[0]; _mero_ctlout = fdopen(pfd[1], "a"); if (pipe(pfd) == -1) { Mfprintf(stderr, "unable to create pipe: %s\n", strerror(errno)); MERO_EXIT(1); } d->err = pfd[0]; _mero_ctlerr = fdopen(pfd[1], "a"); d->pid = getpid(); d->type = MERO; d->dbname = "control"; d->next = NULL; /* allow a thread to relock this mutex */ pthread_mutexattr_init(&mta); pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&_mero_topdp_lock, &mta); if ((thret = pthread_create(&tid, NULL, (void *(*)(void *))logListener, (void *)NULL)) != 0) { Mfprintf(oerr, "%s: FATAL: unable to create logthread: %s\n", argv[0], strerror(thret)); MERO_EXIT(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; if ( sigaction(SIGINT, &sa, NULL) == -1 || sigaction(SIGQUIT, &sa, NULL) == -1 || sigaction(SIGTERM, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = huphandler; if (sigaction(SIGHUP, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = segvhandler; if (sigaction(SIGSEGV, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sa.sa_sigaction = childhandler; if (sigaction(SIGCHLD, &sa, NULL) == -1) { Mfprintf(oerr, "%s: FATAL: unable to create signal handlers: %s\n", argv[0], strerror(errno)); MERO_EXIT(1); } /* make sure we will be able to write our pid */ if ((pidfile = fopen(pidfilename, "w")) == NULL) { Mfprintf(stderr, "unable to open '%s%s%s' for writing: %s\n", pidfilename[0] != '/' ? dbfarm : "", pidfilename[0] != '/' ? "/" : "", pidfilename, strerror(errno)); MERO_EXIT(1); } msab_dbfarminit(dbfarm); /* write out the pid */ Mfprintf(pidfile, "%d\n", (int)d->pid); fclose(pidfile); Mfprintf(stdout, "Merovingian %s (%s) starting\n", MERO_VERSION, MONETDB_RELEASE); Mfprintf(stdout, "monitoring dbfarm %s\n", dbfarm); /* open up connections */ if ( (e = openConnectionTCP(&sock, port, stdout)) == NO_ERR && /* coverity[operator_confusion] */ (unlink(control_usock) | unlink(mapi_usock) | 1) && (e = openConnectionUNIX(&socku, mapi_usock, 0, stdout)) == NO_ERR && (discovery == 0 || (e = openConnectionUDP(&usock, port)) == NO_ERR) && (e = openConnectionUNIX(&unsock, control_usock, S_IRWXO, _mero_ctlout)) == NO_ERR ) { pthread_t ctid = 0; pthread_t dtid = 0; if (discovery == 1) { _mero_broadcastsock = socket(AF_INET, SOCK_DGRAM, 0); ret = 1; if ((setsockopt(_mero_broadcastsock, SOL_SOCKET, SO_BROADCAST, &ret, sizeof(ret))) == -1) { Mfprintf(stderr, "cannot create broadcast package, " "discovery services disabled\n"); close(usock); usock = -1; } _mero_broadcastaddr.sin_family = AF_INET; _mero_broadcastaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); /* the target port is our configured port, not elegant, but how * else can we do it? can't broadcast to all ports or something */ _mero_broadcastaddr.sin_port = htons(port); } /* From this point merovingian considers itself to be in position to * start running, so flag the parent we will have fun. */ MERO_EXIT(0); /* Paranoia umask, but good, because why would people have to sniff * our private parts? */ umask(S_IRWXG | S_IRWXO); /* handle control commands */ if ((thret = pthread_create(&ctid, NULL, (void *(*)(void *))controlRunner, (void *)&unsock)) != 0) { Mfprintf(stderr, "unable to create control command thread: %s\n", strerror(thret)); ctid = 0; } /* start neighbour discovery and notification thread */ if (usock >= 0 && (thret = pthread_create(&dtid, NULL, (void *(*)(void *))discoveryRunner, (void *)&usock)) != 0) { Mfprintf(stderr, "unable to start neighbour discovery thread: %s\n", strerror(thret)); dtid = 0; } /* handle external connections main loop */ e = acceptConnections(sock, socku); /* wait for the control runner and discovery thread to have * finished announcing they're going down */ close(unsock); if (ctid != 0) pthread_join(ctid, NULL); if (usock >= 0) { close(usock); if (dtid != 0) pthread_join(dtid, NULL); } } /* control channel is already closed at this point */ if (unsock != -1 && unlink(control_usock) == -1) Mfprintf(stderr, "unable to unlink control socket '%s': %s\n", control_usock, strerror(errno)); if (socku != -1 && unlink(mapi_usock) == -1) Mfprintf(stderr, "unable to unlink mapi socket '%s': %s\n", mapi_usock, strerror(errno)); if (e != NO_ERR) { /* console */ Mfprintf(oerr, "%s: %s\n", argv[0], e); /* logfile */ Mfprintf(stderr, "%s\n", e); MERO_EXIT(1); } shutdown: /* stop started mservers */ kv = findConfKey(ckv, "exittimeout"); if (d->next != NULL && atoi(kv->val) > 0) { dpair t; threadlist tl = NULL, tlw = tl; pthread_mutex_lock(&_mero_topdp_lock); t = d->next; while (t != NULL) { if (tl == NULL) { tl = tlw = malloc(sizeof(struct _threadlist)); } else { tlw = tlw->next = malloc(sizeof(struct _threadlist)); } tlw->next = NULL; if ((thret = pthread_create(&(tlw->tid), NULL, (void *(*)(void *))terminateProcess, (void *)t)) != 0) { Mfprintf(stderr, "%s: unable to create thread to terminate " "database '%s': %s\n", argv[0], t->dbname, strerror(thret)); tlw->tid = 0; } t = t->next; } pthread_mutex_unlock(&_mero_topdp_lock); /* wait for all processes to be terminated */ tlw = tl; while (tlw != NULL) { if (tlw->tid != 0 && (argp = pthread_join(tlw->tid, NULL)) != 0) { Mfprintf(stderr, "failed to wait for termination thread: " "%s\n", strerror(argp)); } tl = tlw->next; free(tlw); tlw = tl; } } /* need to do this here, since the logging thread is shut down as * next thing */ Mfprintf(stdout, "Merovingian %s stopped\n", MERO_VERSION); _mero_keep_logging = 0; if (tid != 0 && (argp = pthread_join(tid, NULL)) != 0) { Mfprintf(oerr, "failed to wait for logging thread: %s\n", strerror(argp)); } if (_mero_topdp != NULL) { close(_mero_topdp->out); if (_mero_topdp->out != _mero_topdp->err) close(_mero_topdp->err); } /* remove files that suggest our existence */ unlink(".merovingian_lock"); if (pidfilename != NULL) { unlink(pidfilename); free(pidfilename); } /* mostly for valgrind... */ freeConfFile(ckv); if (_mero_db_props != NULL) { freeConfFile(_mero_db_props); free(_mero_db_props); } if (lockfd >= 0) { MT_lockf(".merovingian_lock", F_ULOCK, 4, 1); close(lockfd); } /* the child's return code at this point doesn't matter, as noone * will see it */ return(0); }