GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
start.c
Go to the documentation of this file.
1/*!
2 * \file db/dbmi_client/start.c
3 *
4 * \brief DBMI Library (client) - open database connection
5 *
6 * SPDX-FileCopyrightText: 1999-2008 GRASS Development Team
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 *
9 * \author Joel Jones (CERL/UIUC), Radim Blazek
10 */
11
12#include <string.h>
13#include <stdlib.h>
14#include <unistd.h>
15
16#ifdef _WIN32
17#include <windows.h>
18#include <process.h>
19#include <fcntl.h>
20#endif
21
22#include <grass/spawn.h>
23#include <grass/dbmi.h>
24
25#define READ 0
26#define WRITE 1
27
28static void close_on_exec(int fd)
29{
30#ifndef _WIN32
31 int flags = fcntl(fd, F_GETFD);
32
33 fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
34#endif
35}
36
37/*!
38 \brief Initialize a new dbDriver for db transaction.
39
40 If <i>name</i> is NULL, the db name will be assigned
41 connection.driverName.
42
43 \param name driver name
44
45 \return pointer to dbDriver structure
46 \return NULL on error
47 */
49{
51 dbDbmscap *list, *cur;
52 const char *startup;
53 int p1[2], p2[2];
54 int pid;
55 int stat;
57 char ebuf[5];
58
59 /* Set some environment variables which are later read by driver.
60 * This is necessary when application is running without GISRC file and all
61 * gis variables are set by application.
62 * Even if GISRC is set, application may change some variables during
63 * runtime, if for example reads data from different gdatabase, location or
64 * mapset */
65
66 /* setenv() is not portable, putenv() is POSIX, putenv() in glibc 2.0-2.1.1
67 * doesn't conform to SUSv2, G_putenv() as well, but that is what we want,
68 * makes a copy of string */
70 G_debug(3, "G_GISRC_MODE_MEMORY\n");
71 snprintf(ebuf, sizeof(ebuf), "%d", G_GISRC_MODE_MEMORY);
72 G_putenv("GRASS_DB_DRIVER_GISRC_MODE",
73 ebuf); /* to tell driver that it must read variables */
74
75 if (G_getenv_nofatal("DEBUG")) {
76 G_putenv("DEBUG", G_getenv_nofatal("DEBUG"));
77 }
78 else {
79 G_putenv("DEBUG", "0");
80 }
81
82 G_putenv("GISDBASE", G_getenv_nofatal("GISDBASE"));
83 G_putenv("LOCATION_NAME", G_getenv_nofatal("LOCATION_NAME"));
84 G_putenv("MAPSET", G_getenv_nofatal("MAPSET"));
85 }
86 else {
87 /* Warning: GISRC_MODE_MEMORY _must_ be set to G_GISRC_MODE_FILE,
88 * because the module can be run from an application which previously
89 * set environment variable to G_GISRC_MODE_MEMORY */
90 snprintf(ebuf, sizeof(ebuf), "%d", G_GISRC_MODE_FILE);
91 G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
92 }
93
94 /* read the dbmscap file */
95 if (NULL == (list = db_read_dbmscap()))
96 return (dbDriver *)NULL;
97
98 /* if name is empty use connection.driverName, added by RB 4/2000 */
99 if (name == NULL || name[0] == '\0') {
101 if (NULL == (name = connection.driverName))
102 return (dbDriver *)NULL;
103 }
104
105 /* find this system name */
106 for (cur = list; cur; cur = cur->next)
107 if (strcmp(cur->driverName, name) == 0)
108 break;
109 if (cur == NULL) {
110 char msg[256];
111
113 snprintf(msg, sizeof(msg), "%s: no such driver available", name);
114 db_error(msg);
115 return (dbDriver *)NULL;
116 }
117
118 /* allocate a driver structure */
119 driver = (dbDriver *)db_malloc(sizeof(dbDriver));
120 if (driver == NULL) {
122 return (dbDriver *)NULL;
123 }
124
125 /* copy the relevant info from the dbmscap entry into the driver structure
126 */
127 db_copy_dbmscap_entry(&driver->dbmscap, cur);
128 startup = driver->dbmscap.startup;
129
130 /* free the dbmscap list */
132
133 /* run the driver as a child process and create pipes to its stdin, stdout
134 */
135
136#ifdef _WIN32
137#define pipe(fds) _pipe(fds, 250000, _O_BINARY | _O_NOINHERIT)
138#endif
139
140 /* open the pipes */
141 if ((pipe(p1) < 0) || (pipe(p2) < 0)) {
142 db_syserror("can't open any pipes");
143 return (dbDriver *)NULL;
144 }
145
146 close_on_exec(p1[READ]);
147 close_on_exec(p1[WRITE]);
148 close_on_exec(p2[READ]);
149 close_on_exec(p2[WRITE]);
150
151 pid =
154 p2[WRITE], SF_CLOSE_DESCRIPTOR, p2[READ], startup, NULL);
155
156 /* create a child */
157 if (pid < 0) {
158 db_syserror("can't create fork");
159 return (dbDriver *)NULL;
160 }
161
162 close(p1[READ]);
163 close(p2[WRITE]);
164
165 /* record driver process id in driver struct */
166 driver->pid = pid;
167
168 /* convert pipes to FILE* */
169 driver->send = fdopen(p1[WRITE], "wb");
170 driver->recv = fdopen(p2[READ], "rb");
171
172 /* most systems will have to use unbuffered io to get the send/recv to work
173 */
174#ifndef USE_BUFFERED_IO
175 setbuf(driver->send, NULL);
176 setbuf(driver->recv, NULL);
177#endif
178
179 db__set_protocol_fds(driver->send, driver->recv);
181 driver = NULL;
182
183 return driver;
184}
#define NULL
Definition ccmath.h:32
Main header of GRASS DataBase Management Interface.
#define DB_OK
Definition dbmi.h:69
void db_copy_dbmscap_entry(dbDbmscap *, dbDbmscap *)
Copy dbmscap entry.
Definition dbmscap.c:76
dbDbmscap * db_read_dbmscap(void)
Read dbmscap.
Definition dbmscap.c:95
int db_get_connection(dbConnection *)
Get default DB connection settings for the current mapset.
void db__set_protocol_fds(FILE *, FILE *)
?
void db_error(const char *)
Report error message.
void db_syserror(const char *)
Report system error.
void db_free_dbmscap(dbDbmscap *)
Free dbmscap.
Definition dbmscap.c:261
void * db_malloc(int)
Allocate memory.
int db__recv_return_code(int *)
Receive return code.
Definition ret_codes.c:49
const char * G_getenv_nofatal(const char *)
Get environment variable.
Definition env.c:403
void G_putenv(const char *, const char *)
Sets the UNIX environment variable name to value.
Definition putenv.c:29
int G_get_gisrc_mode(void)
Get info where variables are stored.
Definition env.c:71
int G_debug(int, const char *,...) __attribute__((format(printf
int G_spawn_ex(const char *command,...)
Spawn new process based on command.
Definition spawn.c:897
Header file for msvc/fcntl.c.
#define G_GISRC_MODE_FILE
Definition gis.h:182
#define G_GISRC_MODE_MEMORY
Definition gis.h:183
const char * name
Definition named_colr.c:6
#define SF_CLOSE_DESCRIPTOR
Definition spawn.h:19
#define SF_REDIRECT_DESCRIPTOR
Definition spawn.h:18
#define SF_BACKGROUND
Definition spawn.h:23
dbDriver * db_start_driver(const char *name)
Initialize a new dbDriver for db transaction.
Definition start.c:48
#define WRITE
Definition start.c:26
#define READ
Definition start.c:25
#define fdopen
Definition stdio.h:6
char driverName[256]
Definition dbmi.h:151
struct _dbmscap * next
Definition dbmi.h:154
Definition manage.h:4
#define close
Definition unistd.h:8