GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
start.c
Go to the documentation of this file.
1 
15 #include <string.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 
19 #ifdef __MINGW32__
20 #include <windows.h>
21 #include <process.h>
22 #include <fcntl.h>
23 #endif
24 
25 #include <grass/spawn.h>
26 #include <grass/dbmi.h>
27 
28 #define READ 0
29 #define WRITE 1
30 
31 
43 dbDriver *db_start_driver(const char *name)
44 {
45  dbDriver *driver;
46  dbDbmscap *list, *cur;
47  const char *startup;
48  int p1[2], p2[2];
49  int pid;
50  int stat;
51  dbConnection connection;
52  char ebuf[5];
53 
54  /* Set some environment variables which are later read by driver.
55  * This is necessary when application is running without GISRC file and all
56  * gis variables are set by application.
57  * Even if GISRC is set, application may change some variables during runtime,
58  * if for example reads data from different gdatabase, location or mapset*/
59 
60  /* setenv() is not portable, putenv() is POSIX, putenv() in glibc 2.0-2.1.1 doesn't conform to SUSv2,
61  * G_putenv() as well, but that is what we want, makes a copy of string */
62  if (G_get_gisrc_mode() == G_GISRC_MODE_MEMORY) {
63  G_debug(3, "G_GISRC_MODE_MEMORY\n");
64  sprintf(ebuf, "%d", G_GISRC_MODE_MEMORY);
65  G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf); /* to tell driver that it must read variables */
66 
67  if (G__getenv("DEBUG")) {
68  G_putenv("DEBUG", G__getenv("DEBUG"));
69  }
70  else {
71  G_putenv("DEBUG", "0");
72  }
73 
74  G_putenv("GISDBASE", G__getenv("GISDBASE"));
75  G_putenv("LOCATION_NAME", G__getenv("LOCATION_NAME"));
76  G_putenv("MAPSET", G__getenv("MAPSET"));
77  }
78  else {
79  /* Warning: GISRC_MODE_MEMORY _must_ be set to G_GISRC_MODE_FILE, because the module can be
80  * run from an application which previously set environment variable to G_GISRC_MODE_MEMORY */
81  sprintf(ebuf, "%d", G_GISRC_MODE_FILE);
82  G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf);
83  }
84 
85  /* read the dbmscap file */
86  if (NULL == (list = db_read_dbmscap()))
87  return (dbDriver *) NULL;
88 
89  /* if name is empty use connection.driverName, added by RB 4/2000 */
90  if (name == '\0') {
91  db_get_connection(&connection);
92  if (NULL == (name = connection.driverName))
93  return (dbDriver *) NULL;
94  }
95 
96  /* find this system name */
97  for (cur = list; cur; cur = cur->next)
98  if (strcmp(cur->driverName, name) == 0)
99  break;
100  if (cur == NULL) {
101  char msg[256];
102 
103  db_free_dbmscap(list);
104  sprintf(msg, "%s: no such driver available", name);
105  db_error(msg);
106  return (dbDriver *) NULL;
107  }
108 
109  /* allocate a driver structure */
110  driver = (dbDriver *) db_malloc(sizeof(dbDriver));
111  if (driver == NULL) {
112  db_free_dbmscap(list);
113  return (dbDriver *) NULL;
114  }
115 
116  /* copy the relevant info from the dbmscap entry into the driver structure */
117  db_copy_dbmscap_entry(&driver->dbmscap, cur);
118  startup = driver->dbmscap.startup;
119 
120  /* free the dbmscap list */
121  db_free_dbmscap(list);
122 
123  /* run the driver as a child process and create pipes to its stdin, stdout */
124 
125 #ifdef __MINGW32__
126 #define pipe(fds) _pipe(fds, 250000, _O_BINARY | _O_NOINHERIT)
127 #endif
128 
129  /* open the pipes */
130  if ((pipe(p1) < 0) || (pipe(p2) < 0)) {
131  db_syserror("can't open any pipes");
132  return (dbDriver *) NULL;
133  }
134 
135  pid = G_spawn_ex(startup,
136  SF_BACKGROUND,
137  SF_REDIRECT_DESCRIPTOR, 0, p1[READ],
138  SF_CLOSE_DESCRIPTOR, p1[WRITE],
139  SF_REDIRECT_DESCRIPTOR, 1, p2[WRITE],
140  SF_CLOSE_DESCRIPTOR, p2[READ],
141  startup, NULL);
142 
143  /* create a child */
144  if (pid < 0) {
145  db_syserror("can't create fork");
146  return (dbDriver *) NULL;
147  }
148 
149  close(p1[READ]);
150  close(p2[WRITE]);
151 
152  /* record driver process id in driver struct */
153  driver->pid = pid;
154 
155  /* convert pipes to FILE* */
156  driver->send = fdopen(p1[WRITE], "wb");
157  driver->recv = fdopen(p2[READ], "rb");
158 
159  /* most systems will have to use unbuffered io to get the send/recv to work */
160 #ifndef USE_BUFFERED_IO
161  setbuf(driver->send, NULL);
162  setbuf(driver->recv, NULL);
163 #endif
164 
165  db__set_protocol_fds(driver->send, driver->recv);
166  if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK)
167  driver = NULL;
168 
169  return driver;
170 }
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
struct driver * driver
Definition: driver/init.c:26
void db__set_protocol_fds(FILE *send, FILE *recv)
Definition: xdr.c:71
char * G__getenv(const char *name)
Get environment variable.
Definition: env.c:312
dbDbmscap * db_read_dbmscap(void)
Definition: dbmscap.c:87
string name
Definition: render.py:1314
int G_spawn_ex(const char *command,...)
Spawn new process based on command.
Definition: spawn.c:902
void G_putenv(const char *name, const char *value)
Definition: putenv.c:18
#define WRITE
Definition: start.c:29
void db_error(const char *s)
int db_get_connection(dbConnection *connection)
get default db connection settings
Definition: connect.c:49
int stat
Definition: g3dcolor.c:369
void db_syserror(const char *s)
int G_get_gisrc_mode(void)
Get info where variables are stored.
Definition: env.c:71
void db_copy_dbmscap_entry(dbDbmscap *dst, dbDbmscap *src)
Definition: dbmscap.c:67
void * db_malloc(int n)
int db__recv_return_code(int *ret_code)
Definition: ret_codes.c:18
return NULL
Definition: dbfopen.c:1394
tuple msg
Definition: wxnviz.py:32
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: gis/debug.c:51
void db_free_dbmscap(dbDbmscap *list)
Definition: dbmscap.c:235
dbDriver * db_start_driver(const char *name)
Initialize a new dbDriver for db transaction.
Definition: start.c:43
#define READ
Definition: start.c:28