LCOV - code coverage report
Current view: top level - tools/mserver - mserver5.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 228 394 57.9 %
Date: 2024-10-04 20:04:04 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         318 : monet_hello(void)
     116             : {
     117         318 :         double sz_mem_h;
     118         318 :         const char qc[] = " kMGTPE";
     119         318 :         int qi = 0;
     120             : 
     121         318 :         printf("# MonetDB 5 server v%s", GDKversion());
     122             :         {
     123             : #ifdef MONETDB_RELEASE
     124             :                 printf(" (%s)", MONETDB_RELEASE);
     125             : #else
     126         318 :                 const char *rev = mercurial_revision();
     127         318 :                 if (strcmp(rev, "Unknown") != 0)
     128           0 :                         printf(" (hg id: %s)", rev);
     129             : #endif
     130             :         }
     131             : #ifndef MONETDB_RELEASE
     132         318 :         printf("\n# This is an unreleased version");
     133             : #endif
     134         318 :         printf("\n# Serving database '%s', using %d thread%s\n",
     135             :                    GDKgetenv("gdk_dbname"), GDKnr_threads,
     136         318 :                    (GDKnr_threads != 1) ? "s" : "");
     137         318 :         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         318 :         sz_mem_h = (double) MT_npages() * MT_pagesize();
     145        1272 :         while (sz_mem_h >= 1000.0 && qi < 6) {
     146         954 :                 sz_mem_h /= 1024.0;
     147         954 :                 qi++;
     148             :         }
     149         318 :         printf("# Found %.3f %ciB available main-memory", sz_mem_h, qc[qi]);
     150         318 :         sz_mem_h = (double) GDK_mem_maxsize;
     151         318 :         qi = 0;
     152        1272 :         while (sz_mem_h >= 1000.0 && qi < 6) {
     153         954 :                 sz_mem_h /= 1024.0;
     154         954 :                 qi++;
     155             :         }
     156         318 :         printf(" of which we use %.3f %ciB\n", sz_mem_h, qc[qi]);
     157         318 :         if (GDK_vm_maxsize < GDK_VM_MAXSIZE) {
     158         171 :                 sz_mem_h = (double) GDK_vm_maxsize;
     159         171 :                 qi = 0;
     160         684 :                 while (sz_mem_h >= 1000.0 && qi < 6) {
     161         513 :                         sz_mem_h /= 1024.0;
     162         513 :                         qi++;
     163             :                 }
     164         171 :                 printf("# Virtual memory usage limited to %.3f %ciB\n", sz_mem_h,
     165         171 :                            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         318 :         printf("# Copyright (c) 2024 MonetDB Foundation, all rights reserved\n");
     172         318 :         printf("# Visit https://www.monetdb.org/ for further information\n");
     173             : 
     174             :         // The properties shipped through the performance profiler
     175         318 :         (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         318 :                                         HOST, GDKnr_threads, sz_mem_h, qc[qi], sizeof(oid) * 8);
     190         318 :         fflush(stdout);
     191         318 : }
     192             : 
     193             : static str
     194         320 : absolute_path(const char *s)
     195             : {
     196         320 :         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         320 :         return GDKstrdup(s);
     204             : }
     205             : 
     206             : #define BSIZE 8192
     207             : 
     208             : static int
     209         320 : 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         320 :         int maj, min, patch;
     214         320 :         const char *version = GDKlibversion();
     215         320 :         sscanf(version, "%d.%d.%d", &maj, &min, &patch);
     216         320 :         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         320 :         version = mal_version();
     224         320 :         sscanf(version, "%d.%d.%d", &maj, &min, &patch);
     225         320 :         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         320 :         if (GDKinit(set, setlen, embedded, mercurial_revision()) != GDK_SUCCEED)
     235             :                 return 0;
     236             : 
     237             : #ifdef HAVE_SETSID
     238         318 :         setsid();
     239             : #endif
     240         318 :         monet_hello();
     241         318 :         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         317 : handler(int sig)
     264             : {
     265         317 :         (void) sig;
     266         317 :         interrupted = 1;
     267         317 : }
     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         321 : 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         321 :         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         321 :         char *prog = *av;
     303         321 :         opt *set = NULL;
     304         321 :         unsigned grpdebug = 0, debug = 0;
     305         321 :         int setlen = 0;
     306         321 :         str err = MAL_SUCCEED;
     307         321 :         char prmodpath[FILENAME_MAX];
     308         321 :         const char *modpath = NULL;
     309         321 :         char *binpath = NULL;
     310         321 :         char *dbpath = NULL;
     311         321 :         char *dbextra = NULL;
     312         321 :         char *dbtrace = NULL;
     313         321 :         bool inmemory = false;
     314         321 :         bool readpwdxit = false;
     315         321 :         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             : 
     343             :                 {NULL, 0, NULL, 0}
     344             :         };
     345             : 
     346             : #define MAX_MODULES 32
     347         321 :         char *modules[MAX_MODULES + 1];
     348         321 :         int mods = 0;
     349             : 
     350         321 :         modules[mods++] = "sql";
     351         321 :         modules[mods++] = "generator";
     352             : #ifdef HAVE_GEOM
     353         321 :         modules[mods++] = "geom";
     354             : #endif
     355             : #ifdef HAVE_LIBR
     356             :         /* TODO check for used */
     357         321 :         modules[mods++] = "rapi";
     358             : #endif
     359             : #ifdef HAVE_LIBPY3
     360             :         /* TODO check for used */
     361         321 :         modules[mods++] = "pyapi3";
     362             : #endif
     363             : #ifdef HAVE_CUDF
     364         321 :         modules[mods++] = "capi";
     365             : #endif
     366             : #ifdef HAVE_FITS
     367         321 :         modules[mods++] = "fits";
     368             : #endif
     369             : #ifdef HAVE_NETCDF
     370         321 :         modules[mods++] = "netcdf";
     371             : #endif
     372         321 :         modules[mods++] = "csv";
     373             : #ifdef HAVE_SHP
     374         321 :         modules[mods++] = "shp";
     375             : #endif
     376             : 
     377             : #if defined(_MSC_VER) && defined(__cplusplus)
     378             :         set_terminate(mserver_abort);
     379             : #endif
     380             : #ifdef _MSC_VER
     381             :         _CrtSetReportMode(_CRT_ERROR, 0);
     382             :         _CrtSetReportMode(_CRT_ASSERT, 0);
     383             :         _set_invalid_parameter_handler(mserver_invalid_parameter_handler);
     384             : #ifdef _TWO_DIGIT_EXPONENT
     385             :         _set_output_format(_TWO_DIGIT_EXPONENT);
     386             : #endif
     387             : #endif
     388         321 :         if (setlocale(LC_CTYPE, "") == NULL) {
     389           0 :                 fprintf(stderr, "cannot set locale\n");
     390           0 :                 exit(1);
     391             :         }
     392             : 
     393         321 :         if (MT_getcwd(monet_cwd, FILENAME_MAX - 1) == NULL) {
     394           0 :                 perror("pwd");
     395           0 :                 fprintf(stderr, "monet_init: could not determine current directory\n");
     396           0 :                 exit(-1);
     397             :         }
     398             : 
     399             :         /* retrieve binpath early (before monet_init) because some
     400             :          * implementations require the working directory when the binary was
     401             :          * called */
     402         321 :         binpath = get_bin_path();
     403             : 
     404         321 :         if (!(setlen = mo_builtin_settings(&set)))
     405           0 :                 usage(prog, -1);
     406             : 
     407        2796 :         for (;;) {
     408        3117 :                 int option_index = 0;
     409             : 
     410        3117 :                 int c = getopt_long(argc, av, "c:d::rs:t::v::?",
     411             :                                                         long_options, &option_index);
     412             : 
     413        3117 :                 if (c == -1)
     414             :                         break;
     415             : 
     416        2797 :                 switch (c) {
     417         812 :                 case 0:
     418         812 :                         if (strcmp(long_options[option_index].name, "in-memory") == 0) {
     419             :                                 inmemory = true;
     420             :                                 break;
     421             :                         }
     422         812 :                         if (strcmp(long_options[option_index].name, "dbpath") == 0) {
     423         320 :                                 size_t optarglen = strlen(optarg);
     424             :                                 /* remove trailing directory separator */
     425         320 :                                 while (optarglen > 0
     426         320 :                                            && (optarg[optarglen - 1] == '/'
     427         320 :                                                    || optarg[optarglen - 1] == '\\'))
     428           0 :                                         optarg[--optarglen] = '\0';
     429         320 :                                 dbpath = absolute_path(optarg);
     430         320 :                                 if (dbpath == NULL)
     431           0 :                                         fprintf(stderr,
     432             :                                                         "#error: can not allocate memory for dbpath\n");
     433             :                                 else
     434         320 :                                         setlen = mo_add_option(&set, setlen, opt_cmdline,
     435             :                                                                                    "gdk_dbpath", dbpath);
     436             :                                 break;
     437             :                         }
     438         492 :                         if (strcmp(long_options[option_index].name, "dbextra") == 0) {
     439         165 :                                 if (dbextra)
     440           0 :                                         fprintf(stderr,
     441             :                                                         "#warning: ignoring multiple --dbextra arguments\n");
     442             :                                 else
     443         165 :                                         dbextra = optarg;
     444             :                                 break;
     445             :                         }
     446             : 
     447         327 :                         if (strcmp(long_options[option_index].name, "dbtrace") == 0) {
     448           0 :                                 size_t optarglen = strlen(optarg);
     449             :                                 /* remove trailing directory separator */
     450           0 :                                 while (optarglen > 0
     451           0 :                                            && (optarg[optarglen - 1] == '/'
     452           0 :                                                    || optarg[optarglen - 1] == '\\'))
     453           0 :                                         optarg[--optarglen] = '\0';
     454           0 :                                 dbtrace = absolute_path(optarg);
     455           0 :                                 if (dbtrace == NULL)
     456           0 :                                         fprintf(stderr,
     457             :                                                         "#error: can not allocate memory for dbtrace\n");
     458             :                                 else
     459           0 :                                         setlen = mo_add_option(&set, setlen, opt_cmdline,
     460             :                                                                                    "gdk_dbtrace", dbtrace);
     461             :                                 break;
     462             :                         }
     463             : 
     464         327 :                         if (strcmp(long_options[option_index].name, "single-user") == 0) {
     465           0 :                                 setlen = mo_add_option(&set, setlen, opt_cmdline,
     466             :                                                                            "gdk_single_user", "yes");
     467           0 :                                 break;
     468             :                         }
     469         327 :                         if (strcmp(long_options[option_index].name, "version") == 0) {
     470           1 :                                 monet_version();
     471           1 :                                 exit(0);
     472             :                         }
     473             :                         /* debugging options */
     474         326 :                         if (strcmp(long_options[option_index].name, "algorithms") == 0) {
     475           0 :                                 grpdebug |= GRPalgorithms;
     476           0 :                                 break;
     477             :                         }
     478         326 :                         if (strcmp(long_options[option_index].name, "forcemito") == 0) {
     479         321 :                                 grpdebug |= GRPforcemito;
     480         321 :                                 break;
     481             :                         }
     482           5 :                         if (strcmp(long_options[option_index].name, "heaps") == 0) {
     483           0 :                                 grpdebug |= GRPheaps;
     484           0 :                                 break;
     485             :                         }
     486           5 :                         if (strcmp(long_options[option_index].name, "io") == 0) {
     487           0 :                                 grpdebug |= GRPio;
     488           0 :                                 break;
     489             :                         }
     490           5 :                         if (strcmp(long_options[option_index].name, "memory") == 0) {
     491           0 :                                 grpdebug |= GRPmemory;
     492           0 :                                 break;
     493             :                         }
     494           5 :                         if (strcmp(long_options[option_index].name, "modules") == 0) {
     495           0 :                                 grpdebug |= GRPmodules;
     496           0 :                                 break;
     497             :                         }
     498           5 :                         if (strcmp(long_options[option_index].name, "performance") == 0) {
     499           0 :                                 grpdebug |= GRPperformance;
     500           0 :                                 break;
     501             :                         }
     502           5 :                         if (strcmp(long_options[option_index].name, "properties") == 0) {
     503           0 :                                 grpdebug |= GRPproperties;
     504           0 :                                 break;
     505             :                         }
     506           5 :                         if (strcmp(long_options[option_index].name, "threads") == 0) {
     507           0 :                                 grpdebug |= GRPthreads;
     508           0 :                                 break;
     509             :                         }
     510           5 :                         if (strcmp(long_options[option_index].name, "transactions") == 0) {
     511           0 :                                 grpdebug |= GRPtransactions;
     512           0 :                                 break;
     513             :                         }
     514           5 :                         if (strcmp(long_options[option_index].name, "read-password-initialize-and-exit") == 0) {
     515             :                                 readpwdxit = true;
     516             :                                 break;
     517             :                         }
     518           5 :                         if (strcmp(long_options[option_index].name, "loadmodule") == 0) {
     519           5 :                                 if (mods < MAX_MODULES)
     520           5 :                                         modules[mods++] = optarg;
     521             :                                 else
     522           0 :                                         fprintf(stderr,
     523             :                                                         "ERROR: maximum number of modules reached\n");
     524             :                                 break;
     525             :                         }
     526           0 :                         if (strcmp(long_options[option_index].name, "without-geom") == 0) {
     527           0 :                                 for (int i = 0; i < mods; i++) {
     528           0 :                                         if (strcmp(modules[i], "geom") == 0) {
     529           0 :                                                 while (i + 1 < mods) {
     530           0 :                                                         modules[i] = modules[i + 1];
     531           0 :                                                         i++;
     532             :                                                 }
     533           0 :                                                 mods--;
     534           0 :                                                 break;
     535             :                                         }
     536             :                                 }
     537             :                                 break;
     538             :                         }
     539           0 :                         usage(prog, -1);
     540             :                         /* not reached */
     541           0 :                 case 'c':
     542             :                         /* coverity[var_deref_model] */
     543           0 :                         setlen = mo_add_option(&set, setlen, opt_cmdline, "config", optarg);
     544           0 :                         break;
     545         320 :                 case 'd':
     546         320 :                         if (optarg) {
     547         320 :                                 char *endarg;
     548         320 :                                 debug |= strtoul(optarg, &endarg, 10);
     549         320 :                                 if (*endarg != '\0') {
     550           0 :                                         fprintf(stderr, "ERROR: wrong format for --debug=%s\n",
     551             :                                                         optarg);
     552           0 :                                         usage(prog, -1);
     553             :                                 }
     554             :                         } else {
     555           0 :                                 debug |= CHECKMASK;
     556             :                         }
     557             :                         break;
     558           3 :                 case 'r':
     559           3 :                         setlen = mo_add_option(&set, setlen, opt_cmdline, "gdk_readonly",
     560             :                                                                    "yes");
     561           3 :                         break;
     562        1662 :                 case 's':{
     563             :                         /* should add option to a list */
     564             :                         /* coverity[var_deref_model] */
     565        1662 :                         char *tmp = strchr(optarg, '=');
     566             : 
     567        1662 :                         if (tmp) {
     568        1662 :                                 *tmp = '\0';
     569        1662 :                                 setlen = mo_add_option(&set, setlen, opt_cmdline, optarg,
     570        1662 :                                                                            tmp + 1);
     571             :                         } else
     572           0 :                                 fprintf(stderr, "ERROR: wrong format %s\n", optarg);
     573             :                 }
     574             :                         break;
     575           0 :                 case '?':
     576             :                         /* a bit of a hack: look at the option that the
     577             :                            current `c' is based on and see if we recognize
     578             :                            it: if -? or --help, exit with 0, else with -1 */
     579           0 :                         usage(prog, strcmp(av[optind - 1], "-?") == 0
     580           0 :                                   || strcmp(av[optind - 1], "--help") == 0 ? 0 : -1);
     581           0 :                 default:
     582           0 :                         fprintf(stderr,
     583             :                                         "ERROR: getopt returned character " "code '%c' 0%o\n", c,
     584             :                                         (unsigned) (uint8_t) c);
     585           0 :                         usage(prog, -1);
     586             :                 }
     587             :         }
     588             : 
     589         320 :         if (optind < argc)
     590           0 :                 usage(prog, -1);
     591             : 
     592         320 :         if (!(setlen = mo_system_config(&set, setlen)))
     593           0 :                 usage(prog, -1);
     594             : 
     595         320 :         if (debug)
     596         320 :                 mo_print_options(set, setlen);
     597             : 
     598         320 :         if (dbpath && inmemory) {
     599           0 :                 fprintf(stderr,
     600             :                                 "!ERROR: both dbpath and in-memory must not be set at the same time\n");
     601           0 :                 exit(1);
     602             :         }
     603             : 
     604         320 :         if (inmemory && readpwdxit) {
     605           0 :                 fprintf(stderr,
     606             :                                 "!ERROR: cannot have both in-memory and read-password-initialize-and-exit\n");
     607           0 :                 exit(1);
     608             :         }
     609             : 
     610         320 :         if (inmemory) {
     611           0 :                 if (BBPaddfarm(NULL, (1U << PERSISTENT) | (1U << TRANSIENT), true) !=
     612             :                         GDK_SUCCEED) {
     613           0 :                         fprintf(stderr, "!ERROR: cannot add in-memory farm\n");
     614           0 :                         exit(1);
     615             :                 }
     616             :         } else {
     617         320 :                 if (dbpath == NULL) {
     618           0 :                         dbpath = absolute_path(mo_find_option(set, setlen, "gdk_dbpath"));
     619           0 :                         if (dbpath == NULL) {
     620           0 :                                 fprintf(stderr,
     621             :                                                 "!ERROR: cannot allocate memory for database directory \n");
     622           0 :                                 exit(1);
     623             :                         }
     624             :                 }
     625         320 :                 if (BBPaddfarm(dbpath, 1U << PERSISTENT, true) != GDK_SUCCEED
     626         475 :                         || BBPaddfarm(dbextra ? dbextra : dbpath, 1U << TRANSIENT,
     627             :                                                   true) != GDK_SUCCEED) {
     628           0 :                         fprintf(stderr, "!ERROR: cannot add farm\n");
     629           0 :                         exit(1);
     630             :                 }
     631         320 :                 GDKfree(dbpath);
     632             :         }
     633             : 
     634         320 :         if (dbtrace) {
     635             :                 /* GDKcreatedir makes sure that all parent directories of dbtrace exist */
     636           0 :                 if (!inmemory && GDKcreatedir(dbtrace) != GDK_SUCCEED) {
     637           0 :                         fprintf(stderr, "!ERROR: cannot create directory for %s\n",
     638             :                                         dbtrace);
     639           0 :                         exit(1);
     640             :                 }
     641           0 :                 GDKfree(dbtrace);
     642             :         }
     643             : 
     644         320 :         GDKsetdebug(debug | grpdebug);  /* add the algorithm tracers */
     645         320 :         if (monet_init(set, setlen, false) == 0) {
     646           2 :                 mo_free_options(set, setlen);
     647           2 :                 if (GDKerrbuf && *GDKerrbuf)
     648           0 :                         fprintf(stderr, "%s\n", GDKerrbuf);
     649           2 :                 exit(1);
     650             :         }
     651         318 :         mo_free_options(set, setlen);
     652             : 
     653         318 :         if (GDKsetenv("monet_version", GDKversion()) != GDK_SUCCEED
     654         318 :                 || GDKsetenv("monet_release",
     655             : #ifdef MONETDB_RELEASE
     656             :                                          MONETDB_RELEASE
     657             : #else
     658             :                                          "unreleased"
     659             : #endif
     660             :                 ) != GDK_SUCCEED) {
     661           0 :                 fprintf(stderr, "!ERROR: GDKsetenv failed\n");
     662           0 :                 exit(1);
     663             :         }
     664             : 
     665         318 :         if ((modpath = GDKgetenv("monet_mod_path")) == NULL) {
     666             :                 /* start probing based on some heuristics given the binary
     667             :                  * location:
     668             :                  * bin/mserver5 -> ../
     669             :                  * libX/monetdb5/lib/
     670             :                  * probe libX = lib, lib32, lib64, lib/64 */
     671             :                 size_t pref;
     672             :                 /* "remove" common prefix of configured BIN and LIB
     673             :                  * directories from LIBDIR */
     674       20352 :                 for (pref = 0; LIBDIR[pref] != 0 && BINDIR[pref] == LIBDIR[pref];
     675       20034 :                          pref++) ;
     676         318 :                 const char *libdirs[] = {
     677         318 :                         &LIBDIR[pref],
     678             :                         "lib",
     679             :                         "lib64",
     680             :                         "lib/64",
     681             :                         "lib32",
     682             :                         NULL,
     683             :                 };
     684         318 :                 struct stat sb;
     685         318 :                 if (binpath != NULL) {
     686         318 :                         char *p = strrchr(binpath, DIR_SEP);
     687         318 :                         if (p != NULL)
     688         318 :                                 *p = '\0';
     689         318 :                         p = strrchr(binpath, DIR_SEP);
     690         318 :                         if (p != NULL) {
     691         318 :                                 *p = '\0';
     692         318 :                                 for (int i = 0; libdirs[i] != NULL; i++) {
     693         318 :                                         int len = snprintf(prmodpath, sizeof(prmodpath),
     694             :                                                                            "%s%c%s%cmonetdb5-%s",
     695             :                                                                            binpath, DIR_SEP, libdirs[i], DIR_SEP,
     696             :                                                                            MONETDB_VERSION);
     697         318 :                                         if (len == -1 || len >= FILENAME_MAX)
     698           0 :                                                 continue;
     699         318 :                                         if (MT_stat(prmodpath, &sb) == 0) {
     700             :                                                 modpath = prmodpath;
     701             :                                                 break;
     702             :                                         }
     703           0 :                                         len = snprintf(prmodpath, sizeof(prmodpath),
     704             :                                                                            "%s%c%s%cmonetdb5",
     705             :                                                                            binpath, DIR_SEP, libdirs[i], DIR_SEP);
     706           0 :                                         if (len == -1 || len >= FILENAME_MAX)
     707           0 :                                                 continue;
     708           0 :                                         if (MT_stat(prmodpath, &sb) == 0) {
     709             :                                                 modpath = prmodpath;
     710             :                                                 break;
     711             :                                         }
     712             :                                 }
     713             :                         } else {
     714           0 :                                 printf("#warning: unusable binary location, "
     715             :                                            "please use --set monet_mod_path=/path/to/... to "
     716             :                                            "allow finding modules\n");
     717           0 :                                 fflush(stdout);
     718             :                         }
     719             :                 } else {
     720           0 :                         printf("#warning: unable to determine binary location, "
     721             :                                    "please use --set monet_mod_path=/path/to/... to "
     722             :                                    "allow finding modules\n");
     723           0 :                         fflush(stdout);
     724             :                 }
     725         318 :                 if (modpath != NULL
     726         318 :                         && GDKsetenv("monet_mod_path", modpath) != GDK_SUCCEED) {
     727           0 :                         fprintf(stderr, "!ERROR: GDKsetenv failed\n");
     728           0 :                         exit(1);
     729             :                 }
     730             :         }
     731             : 
     732         318 :         if (!GDKinmemory(0)) {
     733             :                 /* configure sabaoth to use the right dbpath and active database */
     734         318 :                 msab_dbpathinit(GDKgetenv("gdk_dbpath"));
     735             :                 /* wipe out all cruft, if left over */
     736         318 :                 if ((err = msab_wildRetreat()) != NULL) {
     737             :                         /* just swallow the error */
     738           0 :                         free(err);
     739             :                 }
     740             :                 /* From this point, the server should exit cleanly.  Discussion:
     741             :                  * even earlier?  Sabaoth here registers the server is starting up. */
     742         318 :                 if ((err = msab_registerStarting()) != NULL) {
     743             :                         /* throw the error at the user, but don't die */
     744           0 :                         fprintf(stderr, "!%s\n", err);
     745           0 :                         free(err);
     746             :                 }
     747             :         }
     748             : 
     749             : #ifdef HAVE_SIGACTION
     750             :         {
     751         318 :                 struct sigaction sa;
     752             : 
     753         318 :                 (void) sigemptyset(&sa.sa_mask);
     754         318 :                 sa.sa_flags = 0;
     755         318 :                 sa.sa_handler = handler;
     756         318 :                 if (sigaction(SIGINT, &sa, NULL) == -1
     757         318 :                         || sigaction(SIGQUIT, &sa, NULL) == -1
     758         318 :                         || sigaction(SIGTERM, &sa, NULL) == -1) {
     759           0 :                         fprintf(stderr, "!unable to create signal handlers\n");
     760             :                 }
     761         318 :                 (void) sigemptyset(&sa.sa_mask);
     762         318 :                 sa.sa_flags = 0;
     763         318 :                 sa.sa_handler = handler_usr1;
     764         318 :                 if (sigaction(SIGUSR1, &sa, NULL) == -1) {
     765           0 :                         fprintf(stderr, "!unable to create signal handler for SIGUSR1\n");
     766             :                 }
     767             :         }
     768             : #else
     769             : #ifdef _MSC_VER
     770             :         if (!SetConsoleCtrlHandler(winhandler, TRUE))
     771             :                 fprintf(stderr, "!unable to create console control handler\n");
     772             : #else
     773             :         if (signal(SIGINT, handler) == SIG_ERR)
     774             :                 fprintf(stderr, "!unable to create signal handlers\n");
     775             : #ifdef SIGQUIT
     776             :         if (signal(SIGQUIT, handler) == SIG_ERR)
     777             :                 fprintf(stderr, "!unable to create signal handlers\n");
     778             : #endif
     779             :         if (signal(SIGTERM, handler) == SIG_ERR)
     780             :                 fprintf(stderr, "!unable to create signal handlers\n");
     781             :         if (signal(SIGUSR1, handler_usr1) == SIG_ERR)
     782             :                 fprintf(stderr, "!unable to create signal handler for SIGUSR1\n");
     783             : #endif
     784             : #endif
     785             : 
     786         318 :         if (!GDKinmemory(0)) {
     787         318 :                 str lang = "mal";
     788             :                 /* we inited mal before, so publish its existence */
     789         318 :                 if ((err = msab_marchScenario(lang)) != NULL) {
     790             :                         /* throw the error at the user, but don't die */
     791           0 :                         fprintf(stderr, "!%s\n", err);
     792           0 :                         free(err);
     793             :                 }
     794             :         }
     795             : 
     796         318 :         char secret[1024];
     797             :         {
     798             :                 /* unlock the vault, first see if we can find the file which
     799             :                  * holds the secret */
     800         318 :                 FILE *secretf;
     801         318 :                 size_t len;
     802             : 
     803         318 :                 if (GDKinmemory(0) || GDKgetenv("monet_vault_key") == NULL) {
     804             :                         /* use a default (hard coded, non safe) key */
     805         147 :                         snprintf(secret, sizeof(secret), "%s", "Xas632jsi2whjds8");
     806             :                 } else {
     807         171 :                         if ((secretf = MT_fopen(GDKgetenv("monet_vault_key"), "r")) == NULL) {
     808           0 :                                 fprintf(stderr, "unable to open vault_key_file %s: %s\n",
     809           0 :                                                 GDKgetenv("monet_vault_key"), strerror(errno));
     810             :                                 /* don't show this as a crash */
     811           0 :                                 msab_registerStop();
     812           0 :                                 exit(1);
     813             :                         }
     814         171 :                         len = fread(secret, 1, sizeof(secret), secretf);
     815         171 :                         secret[len] = '\0';
     816         171 :                         len = strlen(secret);   /* secret can contain null-bytes */
     817         171 :                         if (len == 0) {
     818           0 :                                 fprintf(stderr, "vault key has zero-length!\n");
     819             :                                 /* don't show this as a crash */
     820           0 :                                 msab_registerStop();
     821           0 :                                 exit(1);
     822         171 :                         } else if (len < 5) {
     823           0 :                                 fprintf(stderr,
     824             :                                                 "#warning: your vault key is too short "
     825             :                                                 "(%zu), enlarge your vault key!\n", len);
     826             :                         }
     827         171 :                         fclose(secretf);
     828             :                 }
     829         318 :                 if ((err = AUTHunlockVault(secret)) != MAL_SUCCEED) {
     830             :                         /* don't show this as a crash */
     831           0 :                         if (!GDKinmemory(0))
     832           0 :                                 msab_registerStop();
     833           0 :                         fprintf(stderr, "%s\n", err);
     834           0 :                         freeException(err);
     835           0 :                         exit(1);
     836             :                 }
     837         318 :                 if (readpwdxit) {
     838           0 :                         char *secretp;
     839           0 :                         if (fgets(secret, (int) sizeof(secret), stdin) == NULL) {
     840           0 :                                 fprintf(stderr, "!ERROR: no password read\n");
     841           0 :                                 exit(1);
     842             :                         }
     843           0 :                         if ((secretp = strchr(secret, '\n')) == NULL) {
     844           0 :                                 fprintf(stderr, "!ERROR: password too long\n");
     845           0 :                                 exit(1);
     846             :                         }
     847           0 :                         *secretp = '\0';
     848             :                 }
     849             :         }
     850             : 
     851         318 :         modules[mods++] = 0;
     852         636 :         if (mal_init(modules, false, readpwdxit ? secret : NULL, mercurial_revision())) {
     853             :                 /* don't show this as a crash */
     854           0 :                 if (!GDKinmemory(0))
     855           0 :                         msab_registerStop();
     856           0 :                 return 1;
     857             :         }
     858         317 :         if (readpwdxit) {
     859           0 :                 msab_registerStop();
     860           0 :                 return 0;
     861             :         }
     862             : 
     863         317 :         emergencyBreakpoint();
     864             : 
     865         317 :         if (!GDKinmemory(0) && (err = msab_registerStarted()) != NULL) {
     866             :                 /* throw the error at the user, but don't die */
     867           0 :                 fprintf(stderr, "!%s\n", err);
     868           0 :                 free(err);
     869             :         }
     870             : 
     871             :         /* return all our free bats to global pool */
     872         317 :         BBPrelinquishbats();
     873             : 
     874             : #ifdef _MSC_VER
     875             :         printf("# MonetDB server is started. To stop server press Ctrl-C.\n");
     876             :         fflush(stdout);
     877             : #endif
     878             : 
     879             :         /* why busy wait ? */
     880       15729 :         while (!interrupted && !GDKexiting()) {
     881       15412 :                 if (usr1_interrupted) {
     882         116 :                         usr1_interrupted = 0;
     883             :                         /* print some useful information */
     884         116 :                         GDKprintinfo();
     885         116 :                         fflush(stdout);
     886             :                 }
     887       15412 :                 MT_sleep_ms(100);               /* pause(), except for sys.shutdown() */
     888             :         }
     889             : 
     890             :         /* mal_exit calls exit, so statements after this call will
     891             :          * never get reached */
     892         317 :         mal_exit(0);
     893             : 
     894             :         return 0;
     895             : }

Generated by: LCOV version 1.14