GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
login.c
Go to the documentation of this file.
1 /*!
2  \file lib/db/dbmi_base/login.c
3 
4  \brief DBMI Library (base) - login settings
5 
6  (C) 1999-2015 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public
9  License (>=v2). Read the file COPYING that comes with GRASS
10  for details.
11 
12  \author Joel Jones (CERL/UIUC), Radim Blazek
13 */
14 
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include <grass/gis.h>
23 #include <grass/dbmi.h>
24 #include <grass/glocale.h>
25 
26 typedef struct
27 {
28  char *driver;
29  char *database;
30  char *user;
31  char *password;
32  char *host;
33  char *port;
34 } DATA;
35 
36 typedef struct
37 {
38  int n, a;
39  DATA *data;
40 } LOGIN;
41 
42 static const char *login_filename(void)
43 {
44  static char *file;
45 
46  if (!file) {
47  file = (char *)db_malloc(GPATH_MAX);
48  sprintf(file, "%s%cdblogin", G_config_path(), HOST_DIRSEP);
49  }
50  return file;
51 }
52 
53 static void init_login(LOGIN * login)
54 {
55  login->n = 0;
56  login->a = 10;
57 
58  login->data = (DATA *) malloc(login->a * sizeof(DATA));
59 }
60 
61 static void add_login(LOGIN * login, const char *dr, const char *db, const char *usr,
62  const char *pwd, const char *host, const char *port, int idx)
63 {
64  int login_idx;
65 
66  G_debug(3, "add_login(): drv='%s' db='%s' usr='%s' pwd='%s' host='%s', port='%s'",
67  dr, db, usr ? usr : "null", pwd ? pwd : "null", host ? host : "null",
68  port ? port : "null");
69 
70  if (login->n == login->a) {
71  login->a += 10;
72  login->data =
73  (DATA *) realloc((void *)login->data, login->a * sizeof(DATA));
74  }
75  if (idx > -1 && idx < login->n) {
76  login_idx = idx;
77  }
78  else {
79  login_idx = login->n;
80  login->n++;
81  }
82  login->data[login_idx].driver = G_store(dr);
83  login->data[login_idx].database = G_store(db);
84  login->data[login_idx].user = G_store(usr ? usr : "");
85  login->data[login_idx].password = G_store(pwd ? pwd : "");
86  login->data[login_idx].host = G_store(host ? host : "");
87  login->data[login_idx].port = G_store(port ? port : "");
88 }
89 
90 /*
91  Read the DB login file if it exists
92  return: -1 error (cannot read file)
93  number of items (0 also if file does not exist)
94  */
95 static int read_file(LOGIN * login)
96 {
97  int ret;
98  const char *file;
99  FILE *fd;
100  char buf[DB_SQL_MAX];
101  char **tokens;
102 
103  login->n = 0;
104  file = login_filename();
105 
106  G_debug(3, "read_file(): DB login file = <%s>", file);
107 
108  if (access(file, F_OK) != 0) {
109  G_debug(3, "login file does not exist");
110  return 0;
111  }
112 
113  fd = fopen(file, "r");
114  if (fd == NULL) {
115  G_warning(_("Unable to read file '%s'"), file);
116  return -1;
117  }
118 
119  while (G_getl2(buf, 2000, fd)) {
120  G_chop(buf);
121 
122  tokens = G_tokenize(buf, "|");
123  ret = G_number_of_tokens(tokens);
124 
125  if (ret < 2) {
126  G_warning(_("Login file (%s) corrupted (line: %s)"), file, buf);
127  G_free_tokens(tokens);
128  continue;
129  }
130 
131  add_login(login,
132  tokens[0], /* driver */
133  tokens[1], /* database */
134  ret > 2 ? tokens[2] : NULL, /* user*/
135  ret > 3 ? tokens[3] : NULL, /* password */
136  ret > 4 ? tokens[4] : NULL, /* host */
137  ret > 5 ? tokens[5] : NULL, /* port */
138  -1);
139  G_free_tokens(tokens);
140  }
141 
142  fclose(fd);
143 
144  return (login->n);
145 }
146 
147 /*
148  Write the DB login file
149  return: -1 error (cannot read file)
150  0 OK
151  */
152 static int write_file(LOGIN * login)
153 {
154  int i;
155  const char *file;
156  FILE *fd;
157 
158  file = login_filename();
159 
160  G_debug(3, "write_file(): DB login file = <%s>", file);
161 
162  fd = fopen(file, "w");
163  if (fd == NULL) {
164  G_warning(_("Unable to write file '%s'"), file);
165  return -1;
166  }
167 
168  /* fchmod is not available on Windows */
169  /* fchmod ( fileno(fd), S_IRUSR | S_IWUSR ); */
170  chmod(file, S_IRUSR | S_IWUSR);
171 
172  for (i = 0; i < login->n; i++) {
173  fprintf(fd, "%s|%s", login->data[i].driver, login->data[i].database);
174  if (login->data[i].user) {
175  fprintf(fd, "|%s", login->data[i].user);
176 
177  if (login->data[i].password)
178  fprintf(fd, "|%s", login->data[i].password);
179  }
180  if (login->data[i].host)
181  fprintf(fd, "|%s", login->data[i].host);
182  if (login->data[i].port)
183  fprintf(fd, "|%s", login->data[i].port);
184 
185  fprintf(fd, "\n");
186  }
187 
188  fclose(fd);
189 
190  return 0;
191 }
192 
193 static int set_login(const char *driver, const char *database, const char *user,
194  const char *password, const char *host, const char *port,
195  int overwrite)
196 {
197  int i, found;
198  LOGIN login;
199 
200  G_debug(3, "db_set_login(): drv=[%s] db=[%s] usr=[%s] pwd=[%s] host=[%s] port=[%s]",
201  driver, database, user, password, host, port);
202 
203  init_login(&login);
204 
205  if (read_file(&login) == -1)
206  return DB_FAILED;
207 
208  found = FALSE;
209  for (i = 0; i < login.n; i++) {
210  if (strcmp(login.data[i].driver, driver) == 0 &&
211  strcmp(login.data[i].database, database) == 0) {
212  if (user)
213  login.data[i].user = G_store(user);
214  else
215  login.data[i].user = G_store("");
216 
217  if (password)
218  login.data[i].password = G_store(password);
219  else
220  login.data[i].password = G_store("");
221 
222  found = TRUE;
223  break;
224  }
225  }
226 
227  if (found) {
228  if (overwrite)
229  G_warning(_("DB connection <%s/%s> already exists and will be overwritten"),
230  driver, database ? database : "");
231  else
232  G_fatal_error(_("DB connection <%s/%s> already exists. "
233  "Re-run '%s' with '--%s' flag to overwrite existing settings."),
234  driver, database ? database : "", G_program_name(), "overwrite");
235  }
236 
237  if (!found)
238  add_login(&login, driver, database, user, password, host, port, -1);
239  else
240  add_login(&login, driver, database, user, password, host, port, i);
241 
242  if (write_file(&login) == -1)
243  return DB_FAILED;
244 
245  return DB_OK;
246 }
247 
248 /*!
249  \brief Set login parameters for driver/database
250 
251  \deprecated Use db_set_login2() instead.
252 
253  \todo: GRASS 8: to be replaced by db_set_login2().
254 
255  \param driver driver name
256  \param database database name
257  \param user user name
258  \param password password string
259 
260  \return DB_OK on success
261  \return DB_FAILED on failure
262  */
263 int db_set_login(const char *driver, const char *database, const char *user,
264  const char *password)
265 {
266  return set_login(driver, database, user,
267  password, NULL, NULL, FALSE);
268 }
269 
270 /*!
271  \brief Set login parameters for driver/database
272 
273  \param driver driver name
274  \param database database name
275  \param user user name
276  \param password password string
277  \param host host name
278  \param port
279  \param overwrite TRUE to overwrite existing connections
280 
281  \return DB_OK on success
282  \return DB_FAILED on failure
283  */
284 int db_set_login2(const char *driver, const char *database, const char *user,
285  const char *password, const char *host, const char *port,
286  int overwrite)
287 {
288  return set_login(driver, database, user,
289  password, host, port, overwrite);
290 }
291 
292 static int get_login(const char *driver, const char *database, const char **user,
293  const char **password, const char **host, const char **port)
294 {
295  int i;
296  LOGIN login;
297 
298  G_debug(3, "db_get_login(): drv=[%s] db=[%s]", driver, database);
299 
300  *user = NULL;
301  *password = NULL;
302  *host = NULL;
303  *port = NULL;
304 
305  init_login(&login);
306 
307  if (read_file(&login) == -1)
308  return DB_FAILED;
309 
310  for (i = 0; i < login.n; i++) {
311  if (strcmp(login.data[i].driver, driver) == 0 &&
312  (!database || strcmp(login.data[i].database, database) == 0)) {
313  if (login.data[i].user && strlen(login.data[i].user) > 0)
314  *user = G_store(login.data[i].user);
315  else
316  *user = NULL;
317 
318  if (login.data[i].password && strlen(login.data[i].password) > 0)
319  *password = G_store(login.data[i].password);
320  else
321  *password = NULL;
322 
323  if (login.data[i].host && strlen(login.data[i].host) > 0 && host)
324  *host = G_store(login.data[i].host);
325  else
326  *host = NULL;
327 
328  if (login.data[i].port && strlen(login.data[i].port) > 0 && port)
329  *port = G_store(login.data[i].port);
330  else
331  *port = NULL;
332 
333  break;
334  }
335  }
336 
337  return DB_OK;
338 }
339 
340 /*!
341  \brief Get login parameters for driver/database
342 
343  If driver/database is not found, output arguments are set to NULL.
344 
345  \deprecated Use db_set_login2() instead.
346 
347  \todo: GRASS 8: to be replaced by db_set_login2().
348 
349  \param driver driver name
350  \param database database name (can be NULL)
351  \param[out] user name
352  \param[out] password string
353 
354  \return DB_OK on success
355  \return DB_FAILED on failure
356 */
357 int db_get_login(const char *driver, const char *database, const char **user,
358  const char **password)
359 {
360  return get_login(driver, database, user,
361  password, NULL, NULL);
362 }
363 
364 /*!
365  \brief Get login parameters for driver/database
366 
367  If driver/database is not found, output arguments are set to NULL.
368 
369  \param driver driver name
370  \param database database name (can be NULL)
371  \param[out] user name
372  \param[out] password string
373  \param[out] host name
374  \param[out] port
375 
376  \return DB_OK on success
377  \return DB_FAILED on failure
378 */
379 int db_get_login2(const char *driver, const char *database, const char **user,
380  const char **password, const char **host, const char **port)
381 {
382  return get_login(driver, database, user,
383  password, host, port);
384 }
385 
386 /*!
387  \brief Print all connection settings to file
388 
389  \param fd file where to print settings
390 
391  \return DB_OK on success
392  \return DB_FAILED on failure
393 */
394 int db_get_login_dump(FILE *fd)
395 {
396  int i;
397  LOGIN login;
398 
399  G_debug(3, "db_get_login_dump()");
400 
401  init_login(&login);
402  if (read_file(&login) == -1)
403  return DB_FAILED;
404 
405  for (i = 0; i < login.n; i++) {
406  fprintf(fd, "%s|%s|%s|%s|%s|%s\n",
407  login.data[i].driver,
408  login.data[i].database,
409  login.data[i].user,
410  login.data[i].password,
411  login.data[i].host,
412  login.data[i].port);
413  }
414 
415  return DB_OK;
416 }
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition: getl.c:64
#define TRUE
Definition: gis.h:59
const char * G_program_name(void)
Return module name.
Definition: progrm_nme.c:28
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define DB_SQL_MAX
Definition: dbmi.h:142
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition: gis/token.c:48
#define NULL
Definition: ccmath.h:32
void * malloc(YYSIZE_T)
#define HOST_DIRSEP
Definition: gis.h:223
int db_get_login_dump(FILE *fd)
Print all connection settings to file.
Definition: login.c:394
#define FALSE
Definition: gis.h:63
int G_number_of_tokens(char **)
Return number of tokens.
Definition: gis/token.c:185
const struct driver * driver
Definition: driver/init.c:25
#define GPATH_MAX
Definition: gis.h:180
int db_set_login(const char *driver, const char *database, const char *user, const char *password)
Set login parameters for driver/database.
Definition: login.c:263
int db_set_login2(const char *driver, const char *database, const char *user, const char *password, const char *host, const char *port, int overwrite)
Set login parameters for driver/database.
Definition: login.c:284
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition: strings.c:328
Definition: driver.h:22
#define DB_FAILED
Definition: dbmi.h:72
const char * G_config_path(void)
Get user&#39;s config path directory.
Definition: home.c:98
void G_free_tokens(char **)
Free memory allocated to tokens.
Definition: gis/token.c:204
void G_warning(const char *,...) __attribute__((format(printf
#define file
int db_get_login(const char *driver, const char *database, const char **user, const char **password)
Get login parameters for driver/database.
Definition: login.c:357
#define _(str)
Definition: glocale.h:10
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
void * db_malloc(int)
Allocate memory.
int G_debug(int, const char *,...) __attribute__((format(printf
int db_get_login2(const char *driver, const char *database, const char **user, const char **password, const char **host, const char **port)
Get login parameters for driver/database.
Definition: login.c:379
#define DB_OK
Definition: dbmi.h:71