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