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

Generated by: LCOV version 1.14