GRASS Programmer's Manual 6.4.1(2011)
|
00001 00015 #include <string.h> 00016 #include <stdlib.h> 00017 #include <unistd.h> 00018 00019 #ifdef __MINGW32__ 00020 #include <windows.h> 00021 #include <process.h> 00022 #include <fcntl.h> 00023 #endif 00024 00025 #include <grass/spawn.h> 00026 #include <grass/dbmi.h> 00027 00028 #define READ 0 00029 #define WRITE 1 00030 00031 00043 dbDriver *db_start_driver(const char *name) 00044 { 00045 dbDriver *driver; 00046 dbDbmscap *list, *cur; 00047 const char *startup; 00048 int p1[2], p2[2]; 00049 int pid; 00050 int stat; 00051 dbConnection connection; 00052 char ebuf[5]; 00053 00054 /* Set some environment variables which are later read by driver. 00055 * This is necessary when application is running without GISRC file and all 00056 * gis variables are set by application. 00057 * Even if GISRC is set, application may change some variables during runtime, 00058 * if for example reads data from different gdatabase, location or mapset*/ 00059 00060 /* setenv() is not portable, putenv() is POSIX, putenv() in glibc 2.0-2.1.1 doesn't conform to SUSv2, 00061 * G_putenv() as well, but that is what we want, makes a copy of string */ 00062 if (G_get_gisrc_mode() == G_GISRC_MODE_MEMORY) { 00063 G_debug(3, "G_GISRC_MODE_MEMORY\n"); 00064 sprintf(ebuf, "%d", G_GISRC_MODE_MEMORY); 00065 G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf); /* to tell driver that it must read variables */ 00066 00067 if (G__getenv("DEBUG")) { 00068 G_putenv("DEBUG", G__getenv("DEBUG")); 00069 } 00070 else { 00071 G_putenv("DEBUG", "0"); 00072 } 00073 00074 G_putenv("GISDBASE", G__getenv("GISDBASE")); 00075 G_putenv("LOCATION_NAME", G__getenv("LOCATION_NAME")); 00076 G_putenv("MAPSET", G__getenv("MAPSET")); 00077 } 00078 else { 00079 /* Warning: GISRC_MODE_MEMORY _must_ be set to G_GISRC_MODE_FILE, because the module can be 00080 * run from an application which previously set environment variable to G_GISRC_MODE_MEMORY */ 00081 sprintf(ebuf, "%d", G_GISRC_MODE_FILE); 00082 G_putenv("GRASS_DB_DRIVER_GISRC_MODE", ebuf); 00083 } 00084 00085 /* read the dbmscap file */ 00086 if (NULL == (list = db_read_dbmscap())) 00087 return (dbDriver *) NULL; 00088 00089 /* if name is empty use connection.driverName, added by RB 4/2000 */ 00090 if (name == '\0') { 00091 db_get_connection(&connection); 00092 if (NULL == (name = connection.driverName)) 00093 return (dbDriver *) NULL; 00094 } 00095 00096 /* find this system name */ 00097 for (cur = list; cur; cur = cur->next) 00098 if (strcmp(cur->driverName, name) == 0) 00099 break; 00100 if (cur == NULL) { 00101 char msg[256]; 00102 00103 db_free_dbmscap(list); 00104 sprintf(msg, "%s: no such driver available", name); 00105 db_error(msg); 00106 return (dbDriver *) NULL; 00107 } 00108 00109 /* allocate a driver structure */ 00110 driver = (dbDriver *) db_malloc(sizeof(dbDriver)); 00111 if (driver == NULL) { 00112 db_free_dbmscap(list); 00113 return (dbDriver *) NULL; 00114 } 00115 00116 /* copy the relevant info from the dbmscap entry into the driver structure */ 00117 db_copy_dbmscap_entry(&driver->dbmscap, cur); 00118 startup = driver->dbmscap.startup; 00119 00120 /* free the dbmscap list */ 00121 db_free_dbmscap(list); 00122 00123 /* run the driver as a child process and create pipes to its stdin, stdout */ 00124 00125 #ifdef __MINGW32__ 00126 #define pipe(fds) _pipe(fds, 250000, _O_BINARY) 00127 #endif 00128 00129 /* open the pipes */ 00130 if ((pipe(p1) < 0) || (pipe(p2) < 0)) { 00131 db_syserror("can't open any pipes"); 00132 return (dbDriver *) NULL; 00133 } 00134 00135 pid = G_spawn_ex(startup, 00136 SF_BACKGROUND, 00137 SF_REDIRECT_DESCRIPTOR, 0, p1[READ], 00138 SF_CLOSE_DESCRIPTOR, p1[WRITE], 00139 SF_REDIRECT_DESCRIPTOR, 1, p2[WRITE], 00140 SF_CLOSE_DESCRIPTOR, p2[READ], 00141 startup, NULL); 00142 00143 /* create a child */ 00144 if (pid < 0) { 00145 db_syserror("can't create fork"); 00146 return (dbDriver *) NULL; 00147 } 00148 00149 close(p1[READ]); 00150 close(p2[WRITE]); 00151 00152 /* record driver process id in driver struct */ 00153 driver->pid = pid; 00154 00155 /* convert pipes to FILE* */ 00156 driver->send = fdopen(p1[WRITE], "wb"); 00157 driver->recv = fdopen(p2[READ], "rb"); 00158 00159 /* most systems will have to use unbuffered io to get the send/recv to work */ 00160 #ifndef USE_BUFFERED_IO 00161 setbuf(driver->send, NULL); 00162 setbuf(driver->recv, NULL); 00163 #endif 00164 00165 db__set_protocol_fds(driver->send, driver->recv); 00166 if (db__recv_return_code(&stat) != DB_OK || stat != DB_OK) 00167 driver = NULL; 00168 00169 return driver; 00170 }