GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-112dd97adf
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  char *driver;
28  char *database;
29  char *user;
30  char *password;
31  char *host;
32  char *port;
33 } DATA;
34 
35 typedef struct {
36  int n, a;
37  DATA *data;
38 } LOGIN;
39 
40 static const char *login_filename(void)
41 {
42  static char *file;
43 
44  if (!file) {
45  file = (char *)db_malloc(GPATH_MAX);
46  sprintf(file, "%s%cdblogin", G_config_path(), HOST_DIRSEP);
47  }
48  return file;
49 }
50 
51 static void init_login(LOGIN *login)
52 {
53  login->n = 0;
54  login->a = 10;
55 
56  login->data = (DATA *)malloc(login->a * sizeof(DATA));
57 }
58 
59 static void add_login(LOGIN *login, const char *dr, const char *db,
60  const char *usr, const char *pwd, const char *host,
61  const char *port, int idx)
62 {
63  int login_idx;
64 
65  G_debug(
66  3,
67  "add_login(): drv='%s' db='%s' usr='%s' pwd='%s' host='%s', port='%s'",
68  dr, db, usr ? usr : "null", pwd ? pwd : "null", host ? host : "null",
69  port ? port : "null");
70 
71  if (login->n == login->a) {
72  login->a += 10;
73  login->data =
74  (DATA *)realloc((void *)login->data, login->a * sizeof(DATA));
75  }
76  if (idx > -1 && idx < login->n) {
77  login_idx = idx;
78  }
79  else {
80  login_idx = login->n;
81  login->n++;
82  }
83  login->data[login_idx].driver = G_store(dr);
84  login->data[login_idx].database = G_store(db);
85  login->data[login_idx].user = G_store(usr ? usr : "");
86  login->data[login_idx].password = G_store(pwd ? pwd : "");
87  login->data[login_idx].host = G_store(host ? host : "");
88  login->data[login_idx].port = G_store(port ? port : "");
89 }
90 
91 /*
92  Read the DB login file if it exists
93  return: -1 error (cannot read file)
94  number of items (0 also if file does not exist)
95  */
96 static int read_file(LOGIN *login)
97 {
98  int ret;
99  const char *file;
100  FILE *fd;
101  char buf[DB_SQL_MAX];
102  char **tokens;
103 
104  login->n = 0;
105  file = login_filename();
106 
107  G_debug(3, "read_file(): DB login file = <%s>", file);
108 
109  if (access(file, F_OK) != 0) {
110  G_debug(3, "login file does not exist");
111  return 0;
112  }
113 
114  fd = fopen(file, "r");
115  if (fd == NULL) {
116  G_warning(_("Unable to read file '%s'"), file);
117  return -1;
118  }
119 
120  while (G_getl2(buf, 2000, fd)) {
121  G_chop(buf);
122 
123  tokens = G_tokenize(buf, "|");
124  ret = G_number_of_tokens(tokens);
125 
126  if (ret < 2) {
127  G_warning(_("Login file (%s) corrupted (line: %s)"), file, buf);
128  G_free_tokens(tokens);
129  continue;
130  }
131 
132  add_login(login, 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,
201  "db_set_login(): drv=[%s] db=[%s] usr=[%s] pwd=[%s] host=[%s] "
202  "port=[%s]",
203  driver, database, user, password, host, port);
204 
205  init_login(&login);
206 
207  if (read_file(&login) == -1)
208  return DB_FAILED;
209 
210  found = FALSE;
211  for (i = 0; i < login.n; i++) {
212  if (strcmp(login.data[i].driver, driver) == 0 &&
213  strcmp(login.data[i].database, database) == 0) {
214  if (user)
215  login.data[i].user = G_store(user);
216  else
217  login.data[i].user = G_store("");
218 
219  if (password)
220  login.data[i].password = G_store(password);
221  else
222  login.data[i].password = G_store("");
223 
224  found = TRUE;
225  break;
226  }
227  }
228 
229  if (found) {
230  if (overwrite)
231  G_warning(_("DB connection <%s/%s> already exists and will be "
232  "overwritten"),
233  driver, database ? database : "");
234  else
235  G_fatal_error(_("DB connection <%s/%s> already exists. "
236  "Re-run '%s' with '--%s' flag to overwrite "
237  "existing settings."),
238  driver, database ? database : "", G_program_name(),
239  "overwrite");
240  }
241 
242  if (!found)
243  add_login(&login, driver, database, user, password, host, port, -1);
244  else
245  add_login(&login, driver, database, user, password, host, port, i);
246 
247  if (write_file(&login) == -1)
248  return DB_FAILED;
249 
250  return DB_OK;
251 }
252 
253 /*!
254  \brief Set login parameters for driver/database
255 
256  \deprecated Use db_set_login2() instead.
257 
258  \todo: GRASS 8: to be replaced by db_set_login2().
259 
260  \param driver driver name
261  \param database database name
262  \param user user name
263  \param password password string
264 
265  \return DB_OK on success
266  \return DB_FAILED on failure
267  */
268 int db_set_login(const char *driver, const char *database, const char *user,
269  const char *password)
270 {
271  return set_login(driver, database, user, password, NULL, NULL, FALSE);
272 }
273 
274 /*!
275  \brief Set login parameters for driver/database
276 
277  \param driver driver name
278  \param database database name
279  \param user user name
280  \param password password string
281  \param host host name
282  \param port
283  \param overwrite TRUE to overwrite existing connections
284 
285  \return DB_OK on success
286  \return DB_FAILED on failure
287  */
288 int db_set_login2(const char *driver, const char *database, const char *user,
289  const char *password, const char *host, const char *port,
290  int overwrite)
291 {
292  return set_login(driver, database, user, password, host, port, overwrite);
293 }
294 
295 static int get_login(const char *driver, const char *database,
296  const char **user, const char **password,
297  const char **host, const char **port)
298 {
299  int i;
300  LOGIN login;
301 
302  G_debug(3, "db_get_login(): drv=[%s] db=[%s]", driver, database);
303 
304  *user = NULL;
305  *password = NULL;
306  *host = NULL;
307  *port = NULL;
308 
309  init_login(&login);
310 
311  if (read_file(&login) == -1)
312  return DB_FAILED;
313 
314  for (i = 0; i < login.n; i++) {
315  if (strcmp(login.data[i].driver, driver) == 0 &&
316  (!database || strcmp(login.data[i].database, database) == 0)) {
317  if (login.data[i].user && strlen(login.data[i].user) > 0)
318  *user = G_store(login.data[i].user);
319  else
320  *user = NULL;
321 
322  if (login.data[i].password && strlen(login.data[i].password) > 0)
323  *password = G_store(login.data[i].password);
324  else
325  *password = NULL;
326 
327  if (login.data[i].host && strlen(login.data[i].host) > 0 && host)
328  *host = G_store(login.data[i].host);
329  else
330  *host = NULL;
331 
332  if (login.data[i].port && strlen(login.data[i].port) > 0 && port)
333  *port = G_store(login.data[i].port);
334  else
335  *port = NULL;
336 
337  break;
338  }
339  }
340 
341  return DB_OK;
342 }
343 
344 /*!
345  \brief Get login parameters for driver/database
346 
347  If driver/database is not found, output arguments are set to NULL.
348 
349  \deprecated Use db_set_login2() instead.
350 
351  \todo: GRASS 8: to be replaced by db_set_login2().
352 
353  \param driver driver name
354  \param database database name (can be NULL)
355  \param[out] user name
356  \param[out] password string
357 
358  \return DB_OK on success
359  \return DB_FAILED on failure
360  */
361 int db_get_login(const char *driver, const char *database, const char **user,
362  const char **password)
363 {
364  return get_login(driver, database, user, password, NULL, NULL);
365 }
366 
367 /*!
368  \brief Get login parameters for driver/database
369 
370  If driver/database is not found, output arguments are set to NULL.
371 
372  \param driver driver name
373  \param database database name (can be NULL)
374  \param[out] user name
375  \param[out] password string
376  \param[out] host name
377  \param[out] port
378 
379  \return DB_OK on success
380  \return DB_FAILED on failure
381  */
382 int db_get_login2(const char *driver, const char *database, const char **user,
383  const char **password, const char **host, const char **port)
384 {
385  return get_login(driver, database, user, password, host, port);
386 }
387 
388 /*!
389  \brief Print all connection settings to file
390 
391  \param fd file where to print settings
392 
393  \return DB_OK on success
394  \return DB_FAILED on failure
395  */
396 int db_get_login_dump(FILE *fd)
397 {
398  int i;
399  LOGIN login;
400 
401  G_debug(3, "db_get_login_dump()");
402 
403  init_login(&login);
404  if (read_file(&login) == -1)
405  return DB_FAILED;
406 
407  for (i = 0; i < login.n; i++) {
408  fprintf(fd, "%s|%s|%s|%s|%s|%s\n", login.data[i].driver,
409  login.data[i].database, login.data[i].user,
410  login.data[i].password, login.data[i].host, login.data[i].port);
411  }
412 
413  return DB_OK;
414 }
#define NULL
Definition: ccmath.h:32
#define DB_SQL_MAX
Definition: dbmi.h:142
#define DB_FAILED
Definition: dbmi.h:72
#define DB_OK
Definition: dbmi.h:71
void * db_malloc(int)
Allocate memory.
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition: getl.c:65
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
const char * G_config_path(void)
Get user's config path directory.
Definition: home.c:98
void G_free_tokens(char **)
Free memory allocated to tokens.
Definition: gis/token.c:198
int G_number_of_tokens(char **)
Return number of tokens.
Definition: gis/token.c:179
const char * G_program_name(void)
Return module name.
Definition: progrm_nme.c:28
char * G_chop(char *)
Chop leading and trailing white spaces.
Definition: strings.c:332
int G_debug(int, const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
char ** G_tokenize(const char *, const char *)
Tokenize string.
Definition: gis/token.c:47
const struct driver * driver
Definition: driver/init.c:25
#define GPATH_MAX
Definition: gis.h:194
#define TRUE
Definition: gis.h:79
#define FALSE
Definition: gis.h:83
#define HOST_DIRSEP
Definition: gis.h:235
#define _(str)
Definition: glocale.h:10
#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:361
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:268
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:382
int db_get_login_dump(FILE *fd)
Print all connection settings to file.
Definition: login.c:396
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:288
void * malloc(YYSIZE_T)
Definition: driver.h:21