LCOV - code coverage report
Current view: top level - tools/mserver - mserver5.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 176 337 52.2 %
Date: 2021-10-13 02:24:04 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include <string.h> /* strerror */
      11             : #include <locale.h>
      12             : #include "monet_options.h"
      13             : #include "mal.h"
      14             : #include "mal_session.h"
      15             : #include "mal_import.h"
      16             : #include "mal_client.h"
      17             : #include "mal_function.h"
      18             : #include "monet_version.h"
      19             : #include "mal_authorize.h"
      20             : #include "msabaoth.h"
      21             : #include "mutils.h"
      22             : 
      23             : #ifdef HAVE_LIBGEN_H
      24             : #include <libgen.h>
      25             : #endif
      26             : 
      27             : #ifndef HAVE_GETOPT_LONG
      28             : #  include "monet_getopt.h"
      29             : #else
      30             : # ifdef HAVE_GETOPT_H
      31             : #  include "getopt.h"
      32             : # endif
      33             : #endif
      34             : 
      35             : #ifdef _MSC_VER
      36             : #include <Psapi.h>      /* for GetModuleFileName */
      37             : #include <crtdbg.h>       /* for _CRT_ERROR, _CRT_ASSERT */
      38             : #endif
      39             : 
      40             : #ifdef _CRTDBG_MAP_ALLOC
      41             : /* Windows only:
      42             :    our definition of new and delete clashes with the one if
      43             :    _CRTDBG_MAP_ALLOC is defined.
      44             :  */
      45             : #undef _CRTDBG_MAP_ALLOC
      46             : #endif
      47             : 
      48             : /* NEEDED? */
      49             : #if defined(_MSC_VER) && defined(__cplusplus)
      50             : #include <eh.h>
      51             : void
      52             : mserver_abort()
      53             : {
      54             :         fprintf(stderr, "\n! mserver_abort() was called by terminate(). !\n");
      55             :         fflush(stderr);
      56             :         exit(0);
      57             : }
      58             : #endif
      59             : 
      60             : #ifdef _MSC_VER
      61             : static void
      62             : mserver_invalid_parameter_handler(
      63             :         const wchar_t *expression,
      64             :         const wchar_t *function,
      65             :         const wchar_t *file,
      66             :         unsigned int line,
      67             :         uintptr_t reserved)
      68             : {
      69             :         (void) expression;
      70             :         (void) function;
      71             :         (void) file;
      72             :         (void) line;
      73             :         (void) reserved;
      74             :         /* the essential bit of this function is that it returns:
      75             :          * we don't want the server to quit when a function is called
      76             :          * with an invalid parameter */
      77             : }
      78             : #endif
      79             : 
      80             : static _Noreturn void usage(char *prog, int xit);
      81             : 
      82             : static void
      83           0 : usage(char *prog, int xit)
      84             : {
      85           0 :         fprintf(stderr, "Usage: %s [options]\n", prog);
      86           0 :         fprintf(stderr, "    --dbpath=<directory>      Specify database location\n");
      87           0 :         fprintf(stderr, "    --dbextra=<directory>     Directory for transient BATs\n");
      88           0 :         fprintf(stderr, "    --dbtrace=<file>          File for produced traces\n");
      89           0 :         fprintf(stderr, "    --in-memory               Run database in-memory only\n");
      90           0 :         fprintf(stderr, "    --config=<config_file>    Use config_file to read options from\n");
      91           0 :         fprintf(stderr, "    --single-user             Allow only one user at a time\n");
      92           0 :         fprintf(stderr, "    --readonly                Safeguard database\n");
      93           0 :         fprintf(stderr, "    --set <option>=<value>    Set configuration option\n");
      94           0 :         fprintf(stderr, "    --help                    Print this list of options\n");
      95           0 :         fprintf(stderr, "    --version                 Print version and compile time info\n");
      96             : 
      97           0 :         fprintf(stderr, "The debug, testing & trace options:\n");
      98           0 :         fprintf(stderr, "     --algorithms\n");
      99           0 :         fprintf(stderr, "     --forcemito\n");
     100           0 :         fprintf(stderr, "     --heaps\n");
     101           0 :         fprintf(stderr, "     --io\n");
     102           0 :         fprintf(stderr, "     --memory\n");
     103           0 :         fprintf(stderr, "     --modules\n");
     104           0 :         fprintf(stderr, "     --performance\n");
     105           0 :         fprintf(stderr, "     --properties\n");
     106           0 :         fprintf(stderr, "     --threads\n");
     107           0 :         fprintf(stderr, "     --transactions\n");
     108           0 :         fprintf(stderr, "     --debug=<bitmask>\n");
     109             : 
     110           0 :         exit(xit);
     111             : }
     112             : 
     113             : /*
     114             :  * Collect some global system properties to relate performance results later
     115             :  */
     116             : static void
     117         254 : monet_hello(void)
     118             : {
     119             :         double sz_mem_h;
     120             :         char  *qc = " kMGTPE";
     121             :         int qi = 0;
     122             : 
     123         254 :         printf("# MonetDB 5 server v%s", GDKversion());
     124             :         {
     125             : #ifdef MONETDB_RELEASE
     126             :                 printf(" (%s)", MONETDB_RELEASE);
     127             : #else
     128         254 :                 const char *rev = mercurial_revision();
     129         254 :                 if (strcmp(rev, "Unknown") != 0)
     130           0 :                         printf(" (hg id: %s)", rev);
     131             : #endif
     132             :         }
     133             : #ifndef MONETDB_RELEASE
     134         254 :         printf("\n# This is an unreleased version");
     135             : #endif
     136         254 :         printf("\n# Serving database '%s', using %d thread%s\n",
     137             :                         GDKgetenv("gdk_dbname"),
     138         254 :                         GDKnr_threads, (GDKnr_threads != 1) ? "s" : "");
     139         254 :         printf("# Compiled for %s/%zubit%s\n",
     140             :                         HOST, sizeof(ptr) * 8,
     141             : #ifdef HAVE_HGE
     142             :                         " with 128bit integers"
     143             : #else
     144             :                         ""
     145             : #endif
     146             :                         );
     147         254 :         sz_mem_h = (double) MT_npages() * MT_pagesize();
     148        1016 :         while (sz_mem_h >= 1000.0 && qi < 6) {
     149         762 :                 sz_mem_h /= 1024.0;
     150         762 :                 qi++;
     151             :         }
     152         254 :         printf("# Found %.3f %ciB available main-memory", sz_mem_h, qc[qi]);
     153         254 :         sz_mem_h = (double) GDK_mem_maxsize;
     154             :         qi = 0;
     155        1016 :         while (sz_mem_h >= 1000.0 && qi < 6) {
     156         762 :                 sz_mem_h /= 1024.0;
     157         762 :                 qi++;
     158             :         }
     159         254 :         printf(" of which we use %.3f %ciB\n", sz_mem_h, qc[qi]);
     160         254 :         if (GDK_vm_maxsize < GDK_VM_MAXSIZE) {
     161         145 :                 sz_mem_h = (double) GDK_vm_maxsize;
     162             :                 qi = 0;
     163         580 :                 while (sz_mem_h >= 1000.0 && qi < 6) {
     164         435 :                         sz_mem_h /= 1024.0;
     165         435 :                         qi++;
     166             :                 }
     167         145 :                 printf("# Virtual memory usage limited to %.3f %ciB\n",
     168         145 :                        sz_mem_h, qc[qi]);
     169             :         }
     170             : #ifdef MONET_GLOBAL_DEBUG
     171             :         printf("# Database path:%s\n", GDKgetenv("gdk_dbpath"));
     172             :         printf("# Module path:%s\n", GDKgetenv("monet_mod_path"));
     173             : #endif
     174         254 :         printf("# Copyright (c) 1993 - July 2008 CWI.\n");
     175         254 :         printf("# Copyright (c) August 2008 - 2021 MonetDB B.V., all rights reserved\n");
     176         254 :         printf("# Visit https://www.monetdb.org/ for further information\n");
     177             : 
     178             :         // The properties shipped through the performance profiler
     179         254 :         (void) snprintf(monet_characteristics, sizeof(monet_characteristics),
     180             :                         "{\n"
     181             :                         "\"version\":\"%s\",\n"
     182             :                         "\"release\":\"%s\",\n"
     183             :                         "\"host\":\"%s\",\n"
     184             :                         "\"threads\":\"%d\",\n"
     185             :                         "\"memory\":\"%.3f %cB\",\n"
     186             :                         "\"oid\":\"%zu\",\n"
     187             :                         "\"packages\":["
     188             : #ifdef HAVE_HGE
     189             :                         "\"huge\""
     190             : #endif
     191             :                         "]\n}",
     192             :                         GDKversion(),
     193             : #ifdef MONETDB_RELEASE
     194             :                         MONETDB_RELEASE,
     195             : #else
     196             :                         "unreleased",
     197             : #endif
     198             :                         HOST, GDKnr_threads,
     199         254 :                         sz_mem_h, qc[qi], sizeof(oid) * 8);
     200         254 : }
     201             : 
     202             : static str
     203         256 : absolute_path(str s)
     204             : {
     205         256 :         if (!MT_path_absolute(s)) {
     206           0 :                 str ret = (str) GDKmalloc(strlen(s) + strlen(monet_cwd) + 2);
     207             : 
     208           0 :                 if (ret)
     209           0 :                         sprintf(ret, "%s%c%s", monet_cwd, DIR_SEP, s);
     210           0 :                 return ret;
     211             :         }
     212         256 :         return GDKstrdup(s);
     213             : }
     214             : 
     215             : #define BSIZE 8192
     216             : 
     217             : static int
     218         256 : monet_init(opt *set, int setlen, bool embedded)
     219             : {
     220             :         /* check that library that we're linked against is compatible with
     221             :          * the one we were compiled with */
     222             :         int maj, min, patch;
     223         256 :         const char *version = GDKlibversion();
     224         256 :         sscanf(version, "%d.%d.%d", &maj, &min, &patch);
     225         256 :         if (maj != GDK_VERSION_MAJOR || min < GDK_VERSION_MINOR) {
     226           0 :                 fprintf(stderr, "Linked GDK library not compatible with the one this was compiled with\n");
     227           0 :                 fprintf(stderr, "Linked version: %s, compiled version: %s\n",
     228             :                                 version, GDK_VERSION);
     229           0 :                 return 0;
     230             :         }
     231         256 :         version = mal_version();
     232         256 :         sscanf(version, "%d.%d.%d", &maj, &min, &patch);
     233         256 :         if (maj != MONETDB5_VERSION_MAJOR || min < MONETDB5_VERSION_MINOR) {
     234           0 :                 fprintf(stderr, "Linked MonetDB5 library not compatible with the one this was compiled with\n");
     235           0 :                 fprintf(stderr, "Linked version: %s, compiled version: %s\n",
     236             :                                 version, MONETDB5_VERSION);
     237           0 :                 return 0;
     238             :         }
     239             : 
     240             :         /* determine Monet's kernel settings */
     241         256 :         if (GDKinit(set, setlen, embedded) != GDK_SUCCEED)
     242             :                 return 0;
     243             : 
     244             : #ifdef HAVE_SETSID
     245         254 :         setsid();
     246             : #endif
     247         254 :         monet_hello();
     248         254 :         return 1;
     249             : }
     250             : 
     251             : static void emergencyBreakpoint(void)
     252             : {
     253             :         /* just a handle to break after system initialization for GDB */
     254             : }
     255             : 
     256             : static volatile sig_atomic_t interrupted = 0;
     257             : 
     258             : #ifdef _MSC_VER
     259             : static BOOL WINAPI
     260             : winhandler(DWORD type)
     261             : {
     262             :         (void) type;
     263             :         interrupted = 1;
     264             :         return TRUE;
     265             : }
     266             : #else
     267             : static void
     268         253 : handler(int sig)
     269             : {
     270             :         (void) sig;
     271         253 :         interrupted = 1;
     272         253 : }
     273             : #endif
     274             : 
     275             : int
     276             : #ifdef _MSC_VER
     277             : wmain(int argc, wchar_t **argv)
     278             : #else
     279         257 : main(int argc, char **av)
     280             : #endif
     281             : {
     282             : #ifdef _MSC_VER
     283             :         char **av = malloc((argc + 1) * sizeof(char *));
     284             :         if (av == NULL) {
     285             :                 fprintf(stderr, "cannot allocate memory for argument conversion\n");
     286             :                 exit(1);
     287             :         }
     288             :         for (int i = 0; i < argc; i++) {
     289             :                 if ((av[i] = wchartoutf8(argv[i])) == NULL) {
     290             :                         fprintf(stderr, "cannot convert argument to UTF-8\n");
     291             :                         exit(1);
     292             :                 }
     293             :         }
     294             :         av[argc] = NULL;
     295             : #endif
     296         257 :         char *prog = *av;
     297         257 :         opt *set = NULL;
     298             :         int grpdebug = 0, debug = 0, setlen = 0;
     299             :         str err = MAL_SUCCEED;
     300             :         char prmodpath[FILENAME_MAX];
     301             :         const char *modpath = NULL;
     302             :         char *binpath = NULL;
     303             :         char *dbpath = NULL;
     304             :         char *dbextra = NULL;
     305             :         char *dbtrace = NULL;
     306             :         bool inmemory = false;
     307             :         bool readpwdxit = false;
     308             :         static struct option long_options[] = {
     309             :                 { "config", required_argument, NULL, 'c' },
     310             :                 { "dbextra", required_argument, NULL, 0 },
     311             :                 { "dbpath", required_argument, NULL, 0 },
     312             :                 { "dbtrace", required_argument, NULL, 0 },
     313             :                 { "debug", optional_argument, NULL, 'd' },
     314             :                 { "help", no_argument, NULL, '?' },
     315             :                 { "in-memory", no_argument, NULL, 0 },
     316             :                 { "readonly", no_argument, NULL, 'r' },
     317             :                 { "set", required_argument, NULL, 's' },
     318             :                 { "single-user", no_argument, NULL, 0 },
     319             :                 { "version", no_argument, NULL, 0 },
     320             : 
     321             :                 { "algorithms", no_argument, NULL, 0 },
     322             :                 { "forcemito", no_argument, NULL, 0 },
     323             :                 { "heaps", no_argument, NULL, 0 },
     324             :                 { "io", no_argument, NULL, 0 },
     325             :                 { "memory", no_argument, NULL, 0 },
     326             :                 { "modules", no_argument, NULL, 0 },
     327             :                 { "performance", no_argument, NULL, 0 },
     328             :                 { "properties", no_argument, NULL, 0 },
     329             :                 { "threads", no_argument, NULL, 0 },
     330             :                 { "transactions", no_argument, NULL, 0 },
     331             : 
     332             :                 { "read-password-initialize-and-exit", no_argument, NULL, 0 },
     333             :                 { "loadmodule", required_argument, NULL, 0 },
     334             : 
     335             :                 { NULL, 0, NULL, 0 }
     336             :         };
     337             : 
     338             : #define MAX_MODULES 32
     339             :         char *modules[MAX_MODULES+1];
     340             :         int mods = 0;
     341             : 
     342         257 :         modules[mods++] = "sql";
     343         257 :         modules[mods++] = "generator";
     344             : #ifdef HAVE_GEOM
     345         257 :         modules[mods++] = "geom";
     346             : #endif
     347             : #ifdef HAVE_LIBR
     348             :         /* TODO check for used */
     349         257 :         modules[mods++] = "rapi";
     350             : #endif
     351             : #ifdef HAVE_LIBPY3
     352             :         /* TODO check for used */
     353         257 :         modules[mods++] = "pyapi3";
     354             : #endif
     355             : #ifdef HAVE_CUDF
     356         257 :         modules[mods++] = "capi";
     357             : #endif
     358             : #ifdef HAVE_FITS
     359         257 :         modules[mods++] = "fits";
     360             : #endif
     361             : #ifdef HAVE_NETCDF
     362         257 :         modules[mods++] = "netcdf";
     363             : #endif
     364             : #ifdef HAVE_SHP
     365         257 :         modules[mods++] = "shp";
     366             : #endif
     367             : 
     368             : #if defined(_MSC_VER) && defined(__cplusplus)
     369             :         set_terminate(mserver_abort);
     370             : #endif
     371             : #ifdef _MSC_VER
     372             :         _CrtSetReportMode(_CRT_ERROR, 0);
     373             :         _CrtSetReportMode(_CRT_ASSERT, 0);
     374             :         _set_invalid_parameter_handler(mserver_invalid_parameter_handler);
     375             : #ifdef _TWO_DIGIT_EXPONENT
     376             :         _set_output_format(_TWO_DIGIT_EXPONENT);
     377             : #endif
     378             : #endif
     379         257 :         if (setlocale(LC_CTYPE, "") == NULL) {
     380           0 :                 fprintf(stderr, "cannot set locale\n");
     381           0 :                 exit(1);
     382             :         }
     383             : 
     384         257 :         if (MT_getcwd(monet_cwd, FILENAME_MAX - 1) == NULL) {
     385           0 :                 perror("pwd");
     386           0 :                 fprintf(stderr,"monet_init: could not determine current directory\n");
     387           0 :                 exit(-1);
     388             :         }
     389             : 
     390             :         /* retrieve binpath early (before monet_init) because some
     391             :          * implementations require the working directory when the binary was
     392             :          * called */
     393         257 :         binpath = get_bin_path();
     394             : 
     395         257 :         if (!(setlen = mo_builtin_settings(&set)))
     396           0 :                 usage(prog, -1);
     397             : 
     398        2323 :         for (;;) {
     399        2580 :                 int option_index = 0;
     400             : 
     401        2580 :                 int c = getopt_long(argc, av, "c:d::rs:t::v::?",
     402             :                                 long_options, &option_index);
     403             : 
     404        2580 :                 if (c == -1)
     405             :                         break;
     406             : 
     407        2324 :                 switch (c) {
     408         696 :                 case 0:
     409         696 :                         if (strcmp(long_options[option_index].name, "in-memory") == 0) {
     410             :                                 inmemory = true;
     411             :                                 break;
     412             :                         }
     413         696 :                         if (strcmp(long_options[option_index].name, "dbpath") == 0) {
     414         256 :                                 size_t optarglen = strlen(optarg);
     415             :                                 /* remove trailing directory separator */
     416         256 :                                 while (optarglen > 0 &&
     417         256 :                                        (optarg[optarglen - 1] == '/' ||
     418             :                                         optarg[optarglen - 1] == '\\'))
     419           0 :                                         optarg[--optarglen] = '\0';
     420         256 :                                 dbpath = absolute_path(optarg);
     421         256 :                                 if( dbpath == NULL)
     422           0 :                                         fprintf(stderr, "#error: can not allocate memory for dbpath\n");
     423             :                                 else
     424         256 :                                         setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_dbpath", dbpath);
     425             :                                 break;
     426             :                         }
     427         440 :                         if (strcmp(long_options[option_index].name, "dbextra") == 0) {
     428         178 :                                 if (dbextra)
     429          33 :                                         fprintf(stderr, "#warning: ignoring multiple --dbextra arguments\n");
     430             :                                 else
     431         145 :                                         dbextra = optarg;
     432             :                                 break;
     433             :                         }
     434             : 
     435         262 :                         if (strcmp(long_options[option_index].name, "dbtrace") == 0) {
     436           0 :                                 size_t optarglen = strlen(optarg);
     437             :                                 /* remove trailing directory separator */
     438           0 :                                 while (optarglen > 0 &&
     439           0 :                                        (optarg[optarglen - 1] == '/' ||
     440             :                                         optarg[optarglen - 1] == '\\'))
     441           0 :                                         optarg[--optarglen] = '\0';
     442           0 :                                 dbtrace = absolute_path(optarg);
     443           0 :                                 if(dbtrace == NULL)
     444           0 :                                         fprintf(stderr, "#error: can not allocate memory for dbtrace\n");
     445             :                                 else
     446           0 :                                         setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_dbtrace", dbtrace);
     447             :                                 break;
     448             :                         }
     449             : 
     450         262 :                         if (strcmp(long_options[option_index].name, "single-user") == 0) {
     451           0 :                                 setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_single_user", "yes");
     452           0 :                                 break;
     453             :                         }
     454         262 :                         if (strcmp(long_options[option_index].name, "version") == 0) {
     455           1 :                                 monet_version();
     456           1 :                                 exit(0);
     457             :                         }
     458             :                         /* debugging options */
     459         261 :                         if (strcmp(long_options[option_index].name, "algorithms") == 0) {
     460           0 :                                 grpdebug |= GRPalgorithms;
     461           0 :                                 break;
     462             :                         }
     463         261 :                         if (strcmp(long_options[option_index].name, "forcemito") == 0) {
     464         257 :                                 grpdebug |= GRPforcemito;
     465         257 :                                 break;
     466             :                         }
     467           4 :                         if (strcmp(long_options[option_index].name, "heaps") == 0) {
     468           0 :                                 grpdebug |= GRPheaps;
     469           0 :                                 break;
     470             :                         }
     471           4 :                         if (strcmp(long_options[option_index].name, "io") == 0) {
     472           0 :                                 grpdebug |= GRPio;
     473           0 :                                 break;
     474             :                         }
     475           4 :                         if (strcmp(long_options[option_index].name, "memory") == 0) {
     476           0 :                                 grpdebug |= GRPmemory;
     477           0 :                                 break;
     478             :                         }
     479           4 :                         if (strcmp(long_options[option_index].name, "modules") == 0) {
     480           0 :                                 grpdebug |= GRPmodules;
     481           0 :                                 break;
     482             :                         }
     483           4 :                         if (strcmp(long_options[option_index].name, "performance") == 0) {
     484           0 :                                 grpdebug |= GRPperformance;
     485           0 :                                 break;
     486             :                         }
     487           4 :                         if (strcmp(long_options[option_index].name, "properties") == 0) {
     488           0 :                                 grpdebug |= GRPproperties;
     489           0 :                                 break;
     490             :                         }
     491           4 :                         if (strcmp(long_options[option_index].name, "threads") == 0) {
     492           0 :                                 grpdebug |= GRPthreads;
     493           0 :                                 break;
     494             :                         }
     495           4 :                         if (strcmp(long_options[option_index].name, "transactions") == 0) {
     496           0 :                                 grpdebug |= GRPtransactions;
     497           0 :                                 break;
     498             :                         }
     499           4 :                         if (strcmp(long_options[option_index].name, "read-password-initialize-and-exit") == 0) {
     500             :                                 readpwdxit = true;
     501             :                                 break;
     502             :                         }
     503           4 :                         if (strcmp(long_options[option_index].name, "loadmodule") == 0) {
     504           4 :                                 if (mods < MAX_MODULES)
     505           4 :                                         modules[mods++]=optarg;
     506             :                                 else
     507           0 :                                         fprintf(stderr, "ERROR: maximum number of modules reached\n");
     508             :                                 break;
     509             :                         }
     510           0 :                         usage(prog, -1);
     511             :                         /* not reached */
     512           0 :                 case 'c':
     513             :                         /* coverity[var_deref_model] */
     514           0 :                         setlen = mo_add_option(&set, setlen, opt_cmdline, "config", optarg);
     515           0 :                         break;
     516         256 :                 case 'd':
     517         256 :                         if (optarg) {
     518             :                                 char *endarg;
     519         256 :                                 debug |= strtol(optarg, &endarg, 10);
     520         256 :                                 if (*endarg != '\0') {
     521           0 :                                         fprintf(stderr, "ERROR: wrong format for --debug=%s\n",
     522             :                                                         optarg);
     523           0 :                                         usage(prog, -1);
     524             :                                 }
     525             :                         } else {
     526           0 :                                 debug |= 1;
     527             :                         }
     528             :                         break;
     529           3 :                 case 'r':
     530           3 :                         setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_readonly", "yes");
     531           3 :                         break;
     532        1369 :                 case 's': {
     533             :                         /* should add option to a list */
     534             :                         /* coverity[var_deref_model] */
     535        1369 :                         char *tmp = strchr(optarg, '=');
     536             : 
     537        1369 :                         if (tmp) {
     538        1369 :                                 *tmp = '\0';
     539        1369 :                                 setlen = mo_add_option(&set, setlen, opt_cmdline, optarg, tmp + 1);
     540             :                         } else
     541           0 :                                 fprintf(stderr, "ERROR: wrong format %s\n", optarg);
     542             :                         }
     543             :                         break;
     544           0 :                 case '?':
     545             :                         /* a bit of a hack: look at the option that the
     546             :                            current `c' is based on and see if we recognize
     547             :                            it: if -? or --help, exit with 0, else with -1 */
     548           0 :                         usage(prog, strcmp(av[optind - 1], "-?") == 0 || strcmp(av[optind - 1], "--help") == 0 ? 0 : -1);
     549           0 :                 default:
     550           0 :                         fprintf(stderr, "ERROR: getopt returned character "
     551             :                                 "code '%c' 0%o\n", c, (unsigned) (uint8_t) c);
     552           0 :                         usage(prog, -1);
     553             :                 }
     554             :         }
     555             : 
     556         256 :         if (optind < argc)
     557           0 :                 usage(prog, -1);
     558             : 
     559         256 :         if (!(setlen = mo_system_config(&set, setlen)))
     560           0 :                 usage(prog, -1);
     561             : 
     562         256 :         if (debug)
     563         256 :                 mo_print_options(set, setlen);
     564             : 
     565         256 :         if (dbpath && inmemory) {
     566           0 :                 fprintf(stderr, "!ERROR: both dbpath and in-memory must not be set at the same time\n");
     567           0 :                 exit(1);
     568             :         }
     569             : 
     570         256 :         if (inmemory && readpwdxit) {
     571           0 :                 fprintf(stderr, "!ERROR: cannot have both in-memory and read-password-initialize-and-exit\n");
     572           0 :                 exit(1);
     573             :         }
     574             : 
     575         256 :         if (!dbpath) {
     576           0 :                 dbpath = absolute_path(mo_find_option(set, setlen, "gdk_dbpath"));
     577           0 :                 if (!dbpath) {
     578           0 :                         fprintf(stderr, "!ERROR: cannot allocate memory for database directory \n");
     579           0 :                         exit(1);
     580             :                 }
     581             :         }
     582         256 :         if (inmemory) {
     583           0 :                 if (BBPaddfarm(NULL, (1U << PERSISTENT) | (1U << TRANSIENT), true) != GDK_SUCCEED) {
     584           0 :                         fprintf(stderr, "!ERROR: cannot add in-memory farm\n");
     585           0 :                         exit(1);
     586             :                 }
     587             :         } else {
     588         512 :                 if (BBPaddfarm(dbpath, 1U << PERSISTENT, true) != GDK_SUCCEED ||
     589         367 :                     BBPaddfarm(dbextra ? dbextra : dbpath, 1U << TRANSIENT, true) != GDK_SUCCEED) {
     590           0 :                         fprintf(stderr, "!ERROR: cannot add farm\n");
     591           0 :                         exit(1);
     592             :                 }
     593         256 :                 if (GDKcreatedir(dbpath) != GDK_SUCCEED) {
     594           0 :                         fprintf(stderr, "!ERROR: cannot create directory for %s\n", dbpath);
     595           0 :                         exit(1);
     596             :                 }
     597             :         }
     598         256 :         GDKfree(dbpath);
     599             : 
     600         256 :         if (dbtrace) {
     601             :                 /* GDKcreatedir makes sure that all parent directories of dbtrace exist */
     602           0 :                 if (GDKcreatedir(dbtrace) != GDK_SUCCEED) {
     603           0 :                         fprintf(stderr, "!ERROR: cannot create directory for %s\n", dbtrace);
     604           0 :                         exit(1);
     605             :                 }
     606           0 :                 GDKfree(dbtrace);
     607             :         }
     608             : 
     609         256 :         if (monet_init(set, setlen, false) == 0) {
     610           2 :                 mo_free_options(set, setlen);
     611           2 :                 if (GDKerrbuf && *GDKerrbuf)
     612           0 :                         fprintf(stderr, "%s\n", GDKerrbuf);
     613           2 :                 exit(1);
     614             :         }
     615         254 :         GDKsetdebug(debug | grpdebug);  /* add the algorithm tracers */
     616         254 :         mo_free_options(set, setlen);
     617             : 
     618         508 :         if (GDKsetenv("monet_version", GDKversion()) != GDK_SUCCEED ||
     619         254 :             GDKsetenv("monet_release",
     620             : #ifdef MONETDB_RELEASE
     621             :                       MONETDB_RELEASE
     622             : #else
     623             :                       "unreleased"
     624             : #endif
     625             :                     ) != GDK_SUCCEED) {
     626           0 :                 fprintf(stderr, "!ERROR: GDKsetenv failed\n");
     627           0 :                 exit(1);
     628             :         }
     629             : 
     630         254 :         if ((modpath = GDKgetenv("monet_mod_path")) == NULL) {
     631             :                 /* start probing based on some heuristics given the binary
     632             :                  * location:
     633             :                  * bin/mserver5 -> ../
     634             :                  * libX/monetdb5/lib/
     635             :                  * probe libX = lib, lib32, lib64, lib/64 */
     636             :                 size_t pref;
     637             :                 /* "remove" common prefix of configured BIN and LIB
     638             :                  * directories from LIBDIR */
     639       16256 :                 for (pref = 0; LIBDIR[pref] != 0 && BINDIR[pref] == LIBDIR[pref]; pref++)
     640             :                         ;
     641         254 :                 const char *libdirs[] = {
     642         254 :                         &LIBDIR[pref],
     643             :                         "lib",
     644             :                         "lib64",
     645             :                         "lib/64",
     646             :                         "lib32",
     647             :                         NULL,
     648             :                 };
     649             :                 struct stat sb;
     650         254 :                 if (binpath != NULL) {
     651         254 :                         char *p = strrchr(binpath, DIR_SEP);
     652         254 :                         if (p != NULL)
     653         254 :                                 *p = '\0';
     654         254 :                         p = strrchr(binpath, DIR_SEP);
     655         254 :                         if (p != NULL) {
     656         254 :                                 *p = '\0';
     657         254 :                                 for (int i = 0; libdirs[i] != NULL; i++) {
     658         254 :                                         int len = snprintf(prmodpath, sizeof(prmodpath), "%s%c%s%cmonetdb5",
     659             :                                                                            binpath, DIR_SEP, libdirs[i], DIR_SEP);
     660         254 :                                         if (len == -1 || len >= FILENAME_MAX)
     661           0 :                                                 continue;
     662         254 :                                         if (MT_stat(prmodpath, &sb) == 0) {
     663             :                                                 modpath = prmodpath;
     664             :                                                 break;
     665             :                                         }
     666             :                                 }
     667             :                         } else {
     668           0 :                                 printf("#warning: unusable binary location, "
     669             :                                            "please use --set monet_mod_path=/path/to/... to "
     670             :                                            "allow finding modules\n");
     671           0 :                                 fflush(NULL);
     672             :                         }
     673             :                 } else {
     674           0 :                         printf("#warning: unable to determine binary location, "
     675             :                                    "please use --set monet_mod_path=/path/to/... to "
     676             :                                    "allow finding modules\n");
     677           0 :                         fflush(NULL);
     678             :                 }
     679         508 :                 if (modpath != NULL &&
     680         254 :                     GDKsetenv("monet_mod_path", modpath) != GDK_SUCCEED) {
     681           0 :                         fprintf(stderr, "!ERROR: GDKsetenv failed\n");
     682           0 :                         exit(1);
     683             :                 }
     684             :         }
     685             : 
     686         254 :         if (!GDKinmemory(0)) {
     687             :                 /* configure sabaoth to use the right dbpath and active database */
     688         254 :                 msab_dbpathinit(GDKgetenv("gdk_dbpath"));
     689             :                 /* wipe out all cruft, if left over */
     690         254 :                 if ((err = msab_wildRetreat()) != NULL) {
     691             :                         /* just swallow the error */
     692           0 :                         free(err);
     693             :                 }
     694             :                 /* From this point, the server should exit cleanly.  Discussion:
     695             :                  * even earlier?  Sabaoth here registers the server is starting up. */
     696         254 :                 if ((err = msab_registerStarting()) != NULL) {
     697             :                         /* throw the error at the user, but don't die */
     698           0 :                         fprintf(stderr, "!%s\n", err);
     699           0 :                         free(err);
     700             :                 }
     701             :         }
     702             : 
     703             : #ifdef HAVE_SIGACTION
     704             :         {
     705             :                 struct sigaction sa;
     706             : 
     707         254 :                 (void) sigemptyset(&sa.sa_mask);
     708         254 :                 sa.sa_flags = 0;
     709         254 :                 sa.sa_handler = handler;
     710         508 :                 if (sigaction(SIGINT, &sa, NULL) == -1 ||
     711         508 :                     sigaction(SIGQUIT, &sa, NULL) == -1 ||
     712         254 :                     sigaction(SIGTERM, &sa, NULL) == -1) {
     713           0 :                         fprintf(stderr, "!unable to create signal handlers\n");
     714             :                 }
     715             :         }
     716             : #else
     717             : #ifdef _MSC_VER
     718             :         if (!SetConsoleCtrlHandler(winhandler, TRUE))
     719             :                 fprintf(stderr, "!unable to create console control handler\n");
     720             : #else
     721             :         if(signal(SIGINT, handler) == SIG_ERR)
     722             :                 fprintf(stderr, "!unable to create signal handlers\n");
     723             : #ifdef SIGQUIT
     724             :         if(signal(SIGQUIT, handler) == SIG_ERR)
     725             :                 fprintf(stderr, "!unable to create signal handlers\n");
     726             : #endif
     727             :         if(signal(SIGTERM, handler) == SIG_ERR)
     728             :                 fprintf(stderr, "!unable to create signal handlers\n");
     729             : #endif
     730             : #endif
     731             : 
     732         254 :         if (!GDKinmemory(0)) {
     733             :                 str lang = "mal";
     734             :                 /* we inited mal before, so publish its existence */
     735         254 :                 if ((err = msab_marchScenario(lang)) != NULL) {
     736             :                         /* throw the error at the user, but don't die */
     737           0 :                         fprintf(stderr, "!%s\n", err);
     738           0 :                         free(err);
     739             :                 }
     740             :         }
     741             : 
     742             :         {
     743             :                 /* unlock the vault, first see if we can find the file which
     744             :                  * holds the secret */
     745             :                 char secret[1024];
     746             :                 char *secretp = secret;
     747             :                 FILE *secretf;
     748             :                 size_t len;
     749             : 
     750         254 :                 if (GDKinmemory(0) || GDKgetenv("monet_vault_key") == NULL) {
     751             :                         /* use a default (hard coded, non safe) key */
     752         254 :                         snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8");
     753             :                 } else {
     754           0 :                         if ((secretf = MT_fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) {
     755           0 :                                 fprintf(stderr,
     756             :                                         "unable to open vault_key_file %s: %s\n",
     757           0 :                                         GDKgetenv("monet_vault_key"), strerror(errno));
     758             :                                 /* don't show this as a crash */
     759           0 :                                 msab_registerStop();
     760           0 :                                 exit(1);
     761             :                         }
     762           0 :                         len = fread(secret, 1, sizeof(secret), secretf);
     763           0 :                         secret[len] = '\0';
     764           0 :                         len = strlen(secret); /* secret can contain null-bytes */
     765           0 :                         if (len == 0) {
     766           0 :                                 fprintf(stderr, "vault key has zero-length!\n");
     767             :                                 /* don't show this as a crash */
     768           0 :                                 msab_registerStop();
     769           0 :                                 exit(1);
     770           0 :                         } else if (len < 5) {
     771           0 :                                 fprintf(stderr, "#warning: your vault key is too short "
     772             :                                                                 "(%zu), enlarge your vault key!\n", len);
     773             :                         }
     774           0 :                         fclose(secretf);
     775             :                 }
     776         254 :                 if ((err = AUTHunlockVault(secret)) != MAL_SUCCEED) {
     777             :                         /* don't show this as a crash */
     778           0 :                         if (!GDKinmemory(0))
     779           0 :                                 msab_registerStop();
     780           0 :                         fprintf(stderr, "%s\n", err);
     781           0 :                         freeException(err);
     782           0 :                         exit(1);
     783             :                 }
     784         254 :                 if (readpwdxit) {
     785           0 :                         if (fgets(secret, (int) sizeof(secret), stdin) == NULL) {
     786           0 :                                 fprintf(stderr, "!ERROR: no password read\n");
     787           0 :                                 exit(1);
     788             :                         }
     789           0 :                         if ((secretp = strchr(secret, '\n')) == NULL) {
     790           0 :                                 fprintf(stderr, "!ERROR: password too long\n");
     791           0 :                                 exit(1);
     792             :                         }
     793           0 :                         *secretp = '\0';
     794           0 :                         err = AUTHinitTables(secret);
     795           0 :                         msab_registerStop();
     796           0 :                         if (err != MAL_SUCCEED) {
     797           0 :                                 fprintf(stderr, "%s\n", err);
     798           0 :                                 freeException(err);
     799           0 :                                 exit(1);
     800             :                         }
     801           0 :                         exit(0);
     802             :                 }
     803             :         }
     804             : 
     805         254 :         modules[mods++] = 0;
     806         254 :         if (mal_init(modules, 0)) {
     807             :                 /* don't show this as a crash */
     808           0 :                 if (!GDKinmemory(0))
     809           0 :                         msab_registerStop();
     810             :                 return 1;
     811             :         }
     812             : 
     813             :         emergencyBreakpoint();
     814             : 
     815         253 :         if (!GDKinmemory(0) && (err = msab_registerStarted()) != NULL) {
     816             :                 /* throw the error at the user, but don't die */
     817           0 :                 fprintf(stderr, "!%s\n", err);
     818           0 :                 free(err);
     819             :         }
     820             : 
     821             : #ifdef SIGHUP
     822             :         // Register signal to GDKtracer (logrotate)
     823         253 :         signal(SIGHUP, GDKtracer_reinit_basic);
     824             : #endif
     825             : 
     826             : #ifdef _MSC_VER
     827             :         printf("# MonetDB server is started. To stop server press Ctrl-C.\n");
     828             : #endif
     829             : 
     830             :         /* why busy wait ? */
     831       15703 :         while (!interrupted && !GDKexiting()) {
     832       15450 :                 MT_sleep_ms(100);
     833             :         }
     834             : 
     835             :         /* mal_exit calls exit, so statements after this call will
     836             :          * never get reached */
     837         253 :         mal_exit(0);
     838             : 
     839             :         return 0;
     840             : }

Generated by: LCOV version 1.14