LCOV - code coverage report
Current view: top level - tools/mserver - mserver5.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 229 397 57.7 %
Date: 2024-12-19 23:10:26 Functions: 6 7 85.7 %

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

Generated by: LCOV version 1.14