GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-c2a9b89919
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 #ifndef _MSC_VER
171  chmod(file, S_IRUSR | S_IWUSR);
172 #endif
173  for (i = 0; i < login->n; i++) {
174  fprintf(fd, "%s|%s", login->data[i].driver, login->data[i].database);
175  if (login->data[i].user) {
176  fprintf(fd, "|%s", login->data[i].user);
177 
178  if (login->data[i].password)
179  fprintf(fd, "|%s", login->data[i].password);
180  }
181  if (login->data[i].host)
182  fprintf(fd, "|%s", login->data[i].host);
183  if (login->data[i].port)
184  fprintf(fd, "|%s", login->data[i].port);
185 
186  fprintf(fd, "\n");
187  }
188 
189  fclose(fd);
190 
191  return 0;
192 }
193 
194 static int set_login(const char *driver, const char *database, const char *user,
195  const char *password, const char *host, const char *port,
196  int overwrite)
197 {
198  int i, found;
199  LOGIN login;
200 
201  G_debug(3,
202  "db_set_login(): drv=[%s] db=[%s] usr=[%s] pwd=[%s] host=[%s] "
203  "port=[%s]",
204  driver, database, user, password, host, port);
205 
206  init_login(&login);
207 
208  if (read_file(&login) == -1)
209  return DB_FAILED;
210 
211  found = FALSE;
212  for (i = 0; i < login.n; i++) {
213  if (strcmp(login.data[i].driver, driver) == 0 &&
214  strcmp(login.data[i].database, database) == 0) {
215  if (user)
216  login.data[i].user = G_store(user);
217  else
218  login.data[i].user = G_store("");
219 
220  if (password)
221  login.data[i].password = G_store(password);
222  else
223  login.data[i].password = G_store("");
224 
225  found = TRUE;
226  break;
227  }
228  }
229 
230  if (found) {
231  if (overwrite)
232  G_warning(_("DB connection <%s/%s> already exists and will be "
233  "overwritten"),
234  driver, database ? database : "");
235  else
236  G_fatal_error(_("DB connection <%s/%s> already exists. "
237  "Re-run '%s' with '--%s' flag to overwrite "
238  "existing settings."),
239  driver, database ? database : "", G_program_name(),
240  "overwrite");
241  }
242 
243  if (!found)
244  add_login(&login, driver, database, user, password, host, port, -1);
245  else
246  add_login(&login, driver, database, user, password, host, port, i);
247 
248  if (write_file(&login) == -1)
249  return DB_FAILED;
250 
251  return DB_OK;
252 }
253 
254 /*!
255  \brief Set login parameters for driver/database
256 
257  \param driver driver name
258  \param database database name
259  \param user user name
260  \param password password string
261  \param host host name
262  \param port
263  \param overwrite TRUE to overwrite existing connections
264 
265  \return DB_OK on success
266  \return DB_FAILED on failure
267  */
268 int db_set_login2(const char *driver, const char *database, const char *user,
269  const char *password, const char *host, const char *port,
270  int overwrite)
271 {
272  return db_set_login(driver, database, user, password, host, port,
273  overwrite);
274 }
275 
276 /*!
277  \brief Set login parameters for driver/database
278 
279  \param driver driver name
280  \param database database name
281  \param user user name
282  \param password password string
283  \param host host name
284  \param port
285  \param overwrite TRUE to overwrite existing connections
286 
287  \return DB_OK on success
288  \return DB_FAILED on failure
289  */
290 int db_set_login(const char *driver, const char *database, const char *user,
291  const char *password, const char *host, const char *port,
292  int overwrite)
293 {
294  return set_login(driver, database, user, password, host, port, overwrite);
295 }
296 
297 static int get_login(const char *driver, const char *database,
298  const char **user, const char **password,
299  const char **host, const char **port)
300 {
301  int i;
302  LOGIN login;
303 
304  G_debug(3, "db_get_login(): drv=[%s] db=[%s]", driver, database);
305 
306  *user = NULL;
307  *password = NULL;
308  *host = NULL;
309  *port = NULL;
310 
311  init_login(&login);
312 
313  if (read_file(&login) == -1)
314  return DB_FAILED;
315 
316  for (i = 0; i < login.n; i++) {
317  if (strcmp(login.data[i].driver, driver) == 0 &&
318  (!database || strcmp(login.data[i].database, database) == 0)) {
319  if (login.data[i].user && strlen(login.data[i].user) > 0)
320  *user = G_store(login.data[i].user);
321  else
322  *user = NULL;
323 
324  if (login.data[i].password && strlen(login.data[i].password) > 0)
325  *password = G_store(login.data[i].password);
326  else
327  *password = NULL;
328 
329  if (login.data[i].host && strlen(login.data[i].host) > 0 && host)
330  *host = G_store(login.data[i].host);
331  else
332  *host = NULL;
333 
334  if (login.data[i].port && strlen(login.data[i].port) > 0 && port)
335  *port = G_store(login.data[i].port);
336  else
337  *port = NULL;
338 
339  break;
340  }
341  }
342 
343  return DB_OK;
344 }
345 
346 /*!
347  \brief Get login parameters for driver/database
348 
349  If driver/database is not found, output arguments are set to NULL.
350 
351  \param driver driver name
352  \param database database name (can be NULL)
353  \param[out] user name
354  \param[out] password string
355  \param[out] host name
356  \param[out] port
357 
358  \return DB_OK on success
359  \return DB_FAILED on failure
360  */
361 int db_get_login2(const char *driver, const char *database, const char **user,
362  const char **password, const char **host, const char **port)
363 {
364  return db_get_login(driver, database, user, password, host, port);
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_login(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: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:361
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:290
int db_get_login_dump(FILE *fd)
Print all connection settings to file.
Definition: login.c:396
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:382
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:268
void * malloc(YYSIZE_T)
Definition: driver.h:27
#define access
Definition: unistd.h:7
#define F_OK
Definition: unistd.h:22