GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
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  \param driver driver name
257  \param database database name
258  \param user user name
259  \param password password string
260  \param host host name
261  \param port
262  \param overwrite TRUE to overwrite existing connections
263 
264  \return DB_OK on success
265  \return DB_FAILED on failure
266  */
267 int db_set_login2(const char *driver, const char *database, const char *user,
268  const char *password, const char *host, const char *port,
269  int overwrite)
270 {
271  return db_set_login(driver, database, user, password, host, port,
272  overwrite);
273 }
274 
275 /*!
276  \brief Set login parameters for driver/database
277 
278  \param driver driver name
279  \param database database name
280  \param user user name
281  \param password password string
282  \param host host name
283  \param port
284  \param overwrite TRUE to overwrite existing connections
285 
286  \return DB_OK on success
287  \return DB_FAILED on failure
288  */
289 int db_set_login(const char *driver, const char *database, const char *user,
290  const char *password, const char *host, const char *port,
291  int overwrite)
292 {
293  return set_login(driver, database, user, password, host, port, overwrite);
294 }
295 
296 static int get_login(const char *driver, const char *database,
297  const char **user, const char **password,
298  const char **host, const char **port)
299 {
300  int i;
301  LOGIN login;
302 
303  G_debug(3, "db_get_login(): drv=[%s] db=[%s]", driver, database);
304 
305  *user = NULL;
306  *password = NULL;
307  *host = NULL;
308  *port = NULL;
309 
310  init_login(&login);
311 
312  if (read_file(&login) == -1)
313  return DB_FAILED;
314 
315  for (i = 0; i < login.n; i++) {
316  if (strcmp(login.data[i].driver, driver) == 0 &&
317  (!database || strcmp(login.data[i].database, database) == 0)) {
318  if (login.data[i].user && strlen(login.data[i].user) > 0)
319  *user = G_store(login.data[i].user);
320  else
321  *user = NULL;
322 
323  if (login.data[i].password && strlen(login.data[i].password) > 0)
324  *password = G_store(login.data[i].password);
325  else
326  *password = NULL;
327 
328  if (login.data[i].host && strlen(login.data[i].host) > 0 && host)
329  *host = G_store(login.data[i].host);
330  else
331  *host = NULL;
332 
333  if (login.data[i].port && strlen(login.data[i].port) > 0 && port)
334  *port = G_store(login.data[i].port);
335  else
336  *port = NULL;
337 
338  break;
339  }
340  }
341 
342  return DB_OK;
343 }
344 
345 /*!
346  \brief Get login parameters for driver/database
347 
348  If driver/database is not found, output arguments are set to NULL.
349 
350  \param driver driver name
351  \param database database name (can be NULL)
352  \param[out] user name
353  \param[out] password string
354  \param[out] host name
355  \param[out] port
356 
357  \return DB_OK on success
358  \return DB_FAILED on failure
359  */
360 int db_get_login2(const char *driver, const char *database, const char **user,
361  const char **password, const char **host, const char **port)
362 {
363  return db_get_login(driver, database, user, password, host, port);
364 }
365 
366 /*!
367  \brief Get login parameters for driver/database
368 
369  If driver/database is not found, output arguments are set to NULL.
370 
371  \param driver driver name
372  \param database database name (can be NULL)
373  \param[out] user name
374  \param[out] password string
375  \param[out] host name
376  \param[out] port
377 
378  \return DB_OK on success
379  \return DB_FAILED on failure
380  */
381 int db_get_login(const char *driver, const char *database, const char **user,
382  const char **password, const char **host, const char **port)
383 {
384  return get_login(driver, database, user, password, host, port);
385 }
386 
387 /*!
388  \brief Print all connection settings to file
389 
390  \param fd file where to print settings
391 
392  \return DB_OK on success
393  \return DB_FAILED on failure
394  */
395 int db_get_login_dump(FILE *fd)
396 {
397  int i;
398  LOGIN login;
399 
400  G_debug(3, "db_get_login_dump()");
401 
402  init_login(&login);
403  if (read_file(&login) == -1)
404  return DB_FAILED;
405 
406  for (i = 0; i < login.n; i++) {
407  fprintf(fd, "%s|%s|%s|%s|%s|%s\n", login.data[i].driver,
408  login.data[i].database, login.data[i].user,
409  login.data[i].password, login.data[i].host, login.data[i].port);
410  }
411 
412  return DB_OK;
413 }
#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:60
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_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:360
int db_set_login(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:289
int db_get_login_dump(FILE *fd)
Print all connection settings to file.
Definition: login.c:395
int db_get_login(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:381
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:267
void * malloc(YYSIZE_T)
Definition: driver.h:21