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, 2025 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 "dotmonetdb.h"
15 : #include "mutils.h"
16 : #include <string.h>
17 :
18 : void
19 162 : parse_dotmonetdb(DotMonetdb *dotfile)
20 : {
21 162 : FILE *config = NULL;
22 162 : char buf[FILENAME_MAX];
23 :
24 162 : if (dotfile == NULL)
25 0 : return;
26 : /* if environment variable DOTMONETDBFILE is set, use it */
27 : /* 1. use $DOTMONETDBFILE (if set but empty do not read config file);
28 : * 2. use .monetdb;
29 : * 3. use ${XDG_CONFIG_HOME-$HOME/.config}/monetdb;
30 : * 4. use $HOME/.monetdb
31 : * (3 is standard shell syntax: use XDG_CONFIG_HOME if set, else use
32 : * $HOME/.config in its place)
33 : */
34 : #ifdef NATIVE_WIN32
35 : wchar_t *cfile;
36 : wchar_t wbuf[FILENAME_MAX];
37 : #define CF "%ls" /* format to print cfile */
38 :
39 : if ((cfile = _wgetenv(L"DOTMONETDBFILE")) == NULL) {
40 : /* no environment variable: use a default */
41 : cfile = L".monetdb";
42 : if ((config = _wfopen(cfile, L"r")) == NULL) {
43 : const wchar_t *xdg = _wgetenv(L"XDG_CONFIG_HOME");
44 : const wchar_t *home = _wgetenv(L"HOME");
45 : int len = -1;
46 : cfile = wbuf;
47 : if (xdg != NULL)
48 : len = _snwprintf(wbuf, sizeof(wbuf), L"%ls%lcmonetdb", xdg, DIR_SEP);
49 : else if (home != NULL)
50 : len = _snwprintf(wbuf, sizeof(wbuf), L"%ls%lc.config%lcmonetdb", home, DIR_SEP, DIR_SEP);
51 : if (len == -1 || len >= FILENAME_MAX || (config = _wfopen(wbuf, L"r")) == NULL) {
52 : if (home) {
53 : len = _snwprintf(wbuf, sizeof(wbuf), L"%ls%lc.monetdb", home, DIR_SEP);
54 : if (len >= 0 && len < FILENAME_MAX)
55 : config = _wfopen(wbuf, L"r");
56 : }
57 : }
58 : }
59 : } else if (*cfile != 0 && (config = _wfopen(cfile, L"r")) == NULL) {
60 : fprintf(stderr, "failed to open file '%ls': %s\n",
61 : cfile, strerror(errno));
62 : }
63 : #else
64 162 : char *cfile;
65 : #define CF "%s" /* format to print cfile */
66 :
67 162 : if ((cfile = getenv("DOTMONETDBFILE")) == NULL) {
68 : /* no environment variable: use a default */
69 2 : cfile = ".monetdb";
70 2 : if ((config = fopen(cfile, "r")) == NULL) {
71 2 : const char *xdg = getenv("XDG_CONFIG_HOME");
72 2 : const char *home = getenv("HOME");
73 2 : int len = -1;
74 2 : cfile = buf;
75 2 : if (xdg != NULL)
76 0 : len = snprintf(buf, sizeof(buf), "%s%cmonetdb", xdg, DIR_SEP);
77 2 : else if (home != NULL)
78 2 : len = snprintf(buf, sizeof(buf), "%s%c.config%cmonetdb", home, DIR_SEP, DIR_SEP);
79 2 : if (len == -1 || len >= FILENAME_MAX || (config = fopen(buf, "r")) == NULL) {
80 2 : if (home) {
81 2 : len = snprintf(buf, sizeof(buf), "%s%c.monetdb", home, DIR_SEP);
82 2 : if (len >= 0 && len < FILENAME_MAX)
83 2 : config = fopen(buf, "r");
84 : }
85 : }
86 : }
87 160 : } else if (*cfile != 0 && (config = fopen(cfile, "r")) == NULL) {
88 0 : fprintf(stderr, "failed to open file '%s': %s\n",
89 0 : cfile, strerror(errno));
90 : }
91 : #endif
92 :
93 162 : *dotfile = (DotMonetdb) {0};
94 :
95 162 : if (config) {
96 : int line = 0;
97 : char *q;
98 480 : while (fgets(buf, sizeof(buf), config) != NULL) {
99 320 : line++;
100 320 : q = strchr(buf, '\n');
101 320 : if (q)
102 320 : *q = 0;
103 320 : if (buf[0] == '\0' || buf[0] == '#')
104 0 : continue;
105 320 : if ((q = strchr(buf, '=')) == NULL) {
106 0 : fprintf(stderr, CF ":%d: syntax error: %s\n",
107 : cfile, line, buf);
108 0 : continue;
109 : }
110 320 : *q++ = '\0';
111 : /* this basically sucks big time, as I can't easily set
112 : * a default, hence I only do things I think are useful
113 : * for now, needs a better solution */
114 320 : if (strcmp(buf, "user") == 0) {
115 160 : dotfile->user = strdup(q);
116 160 : q = NULL;
117 160 : } else if (strcmp(buf, "password") == 0) {
118 160 : dotfile->passwd = strdup(q);
119 160 : q = NULL;
120 0 : } else if (strcmp(buf, "database") == 0) {
121 0 : dotfile->dbname = strdup(q);
122 0 : q = NULL;
123 0 : } else if (strcmp(buf, "host") == 0) {
124 0 : dotfile->host = strdup(q);
125 0 : q = NULL;
126 0 : } else if (strcmp(buf, "language") == 0) {
127 : /* make sure we don't set garbage */
128 0 : if (strcmp(q, "sql") != 0 &&
129 0 : strcmp(q, "mal") != 0) {
130 0 : fprintf(stderr, CF ":%d: unsupported language: %s\n",
131 : cfile, line, q);
132 : }
133 0 : dotfile->language = strdup(q);
134 0 : q = NULL;
135 0 : } else if (strcmp(buf, "save_history") == 0) {
136 0 : if (strcmp(q, "true") == 0 ||
137 0 : strcmp(q, "on") == 0) {
138 0 : dotfile->save_history = true;
139 0 : q = NULL;
140 0 : } else if (strcmp(q, "false") == 0 ||
141 0 : strcmp(q, "off") == 0) {
142 0 : dotfile->save_history = false;
143 0 : q = NULL;
144 : }
145 0 : } else if (strcmp(buf, "format") == 0) {
146 0 : dotfile->output = strdup(q);
147 0 : q = NULL;
148 0 : } else if (strcmp(buf, "width") == 0) {
149 0 : dotfile->pagewidth = atoi(q);
150 0 : q = NULL;
151 0 : } else if (strcmp(buf, "port") == 0) {
152 0 : dotfile->port = atoi(q);
153 0 : q = NULL;
154 : }
155 320 : if (q != NULL)
156 0 : fprintf(stderr, CF ":%d: unknown property: %s\n",
157 : cfile, line, buf);
158 : }
159 160 : fclose(config);
160 : }
161 : }
162 :
163 : void
164 140 : destroy_dotmonetdb(DotMonetdb *dotfile)
165 : {
166 140 : free(dotfile->user);
167 140 : free(dotfile->passwd);
168 140 : free(dotfile->dbname);
169 140 : free(dotfile->host);
170 140 : free(dotfile->output);
171 140 : free(dotfile->language);
172 140 : }
|